* [PATCH/RFC 0/7] Samsung IOMMU videobuf2 allocator and s5p-fimc update
@ 2011-03-04 9:01 Marek Szyprowski
2011-03-04 9:01 ` [PATCH 1/7] ARM: S5PV310: Add platform definitions for FIMC Marek Szyprowski
` (7 more replies)
0 siblings, 8 replies; 29+ messages in thread
From: Marek Szyprowski @ 2011-03-04 9:01 UTC (permalink / raw)
To: linux-arm-kernel
Hello,
This patch series introduces new type of videbuf2 memory allocator -
vb2-s5p-iommu. This allocator can be used only on Samsung SoCs that have
IOMMU module. Currently only Samsung EXYNOS4 (former S5PV310) platform
has SYSMMU modules. The allocator is then used by s5p-fimc driver. To
make it possible some additional changes are required. Mainly platform
support for s5p-fimc for EXYNOS4 machines need to be defined. The
proposed solution has been tested on Universal C210 board (Samsung
S5PC210/EXYNOS4 based).
We decided to use driver private address space mode of the iommu driver.
This way each vb2-s5p-iommu client gets it's own address space for
memory buffers. This reduces kernel virtual memory fragmentation as well
as solves some non-trivial page table updates issues. The drawback is
the fact that the interface for s5p-sysmmu has been changed.
This IOMMU allocator has no dependences on other subsystems besides
Samsung platfrom core. We also ported s5p-mfc and s5p-tv drivers to this
allocator, they will be posted in separate patch series. This will
enable to get them working on EXYNOS4 (S5PV310) platform. Support for
S5PV210/S5PC110 platform still depends on CMA allocator that needs more
discussion on memory management mailing list and development. The
patches with updated s5p-mfc and s5p-tv drivers will follow.
To get FIMC module working on EXYNOS4/UniversalC210 board we also added
support for power domains and power gating.
This patch series contains a collection of patches for various platform
subsystems. Here is a detailed list:
[PATCH 1/7] ARM: S5PV310: Add platform definitions for FIMC
- adds basic platform resources for FIMC modules (for s5p-fimc driver)
[PATCH 2/7] ARM: S5PV310: power domains: fixes and code cleanup
- adds support for block gating in Samsung power domain driver and
performs some cleanup
[PATCH 3/7] ARM: Samsung: update/rewrite Samsung SYSMMU (IOMMU) driver
- a complete rewrite of sysmmu driver for Samsung platform:
- the new version introduces device private page tables (address space)
mode
- simplified the resource management (no more horrible single platform
device with 32 resources is needed)
- some other API chages required by upcoming videobuf2 allocator
[PATCH 4/7] v4l: videobuf2: add Samsung SYSMMU (IOMMU) based allocator
- introduces new memory allocator for videobuf2, it uses s5p-sysmmu
iommu driver, memory for video buffers is acuired by alloc_page() kernel
function
[PATCH 5/7] s5p-fimc: add pm_runtime support
- adds support for pm_runtime in s5p-fimc driver
[PATCH 6/7] s5p-fimc: Add support for vb2-s5p-iommu allocator
- adds support for the newly introduces videbuf2-s5p-iommu allocator
on EXYNOS4 platform
[PATCH 7/7] ARM: S5PC210: enable FIMC on Universal_C210
- adds all required machine definitions to get FIMC modules working
on Universal C210 boards
The patch series is based on git://linuxtv.org/media_tree.git tree,
staging/for_v2.6.39 branch with the following Samsung platform patches:
1. [PATCH] ARM: Samsung: change suspend/resume code to depend on CONFIG_SUSPEND
http://www.mail-archive.com/linux-samsung-soc at vger.kernel.org/msg04025.html
2. [PATCH v2] ARM: S5PC210: add support for i2c PMICs on Universal_C210 board
http://www.mail-archive.com/linux-samsung-soc at vger.kernel.org/msg04029.html
This series has not been rebased onto the latest changes (S5PV310
renamed to EXYNOS4) in
git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git,
for-next branch. We will rebase them soon, but first we want to get
feedback and comments on the s5p-iommu videobuf2 allocator idea.
Best regards
--
Marek Szyprowski
Samsung Poland R&D Center
Complete patch summary:
Andrzej Pietrasiewicz (2):
ARM: Samsung: update/rewrite Samsung SYSMMU (IOMMU) driver
v4l: videobuf2: add Samsung SYSMMU (IOMMU) based allocator
Marek Szyprowski (3):
s5p-fimc: add pm_runtime support
s5p-fimc: Add support for vb2-s5p-iommu allocator
ARM: S5PC210: enable FIMC on Universal_C210
Sylwester Nawrocki (1):
ARM: S5PV310: Add platform definitions for FIMC
Tomasz Stanislawski (1):
ARM: S5PV310: power domains: fixes and code cleanup
arch/arm/mach-s5pv310/Kconfig | 6 +
arch/arm/mach-s5pv310/clock.c | 91 ++
arch/arm/mach-s5pv310/cpu.c | 7 +
arch/arm/mach-s5pv310/dev-pd.c | 93 ++-
arch/arm/mach-s5pv310/dev-sysmmu.c | 582 +++++++++----
arch/arm/mach-s5pv310/include/mach/irqs.h | 40 +-
arch/arm/mach-s5pv310/include/mach/map.h | 8 +
arch/arm/mach-s5pv310/include/mach/regs-clock.h | 12 +
arch/arm/mach-s5pv310/include/mach/regs-sysmmu.h | 23 +-
arch/arm/mach-s5pv310/include/mach/sysmmu.h | 122 ---
arch/arm/mach-s5pv310/mach-universal_c210.c | 20 +
arch/arm/plat-s5p/Kconfig | 22 +-
arch/arm/plat-s5p/Makefile | 1 +
arch/arm/plat-s5p/dev-fimc3.c | 43 +
arch/arm/plat-s5p/include/plat/sysmmu.h | 127 +++
arch/arm/plat-s5p/sysmmu.c | 988 +++++++++++++++-------
arch/arm/plat-samsung/include/plat/devs.h | 3 +-
arch/arm/plat-samsung/include/plat/fimc-core.h | 5 +
arch/arm/plat-samsung/include/plat/pd.h | 1 +
drivers/media/video/Kconfig | 11 +-
drivers/media/video/Makefile | 1 +
drivers/media/video/s5p-fimc/fimc-capture.c | 9 +-
drivers/media/video/s5p-fimc/fimc-core.c | 36 +-
drivers/media/video/s5p-fimc/fimc-mem.h | 87 ++
drivers/media/video/videobuf2-s5p-iommu.c | 444 ++++++++++
include/media/videobuf2-s5p-iommu.h | 50 ++
26 files changed, 2129 insertions(+), 703 deletions(-)
rewrite arch/arm/mach-s5pv310/dev-sysmmu.c (86%)
delete mode 100644 arch/arm/mach-s5pv310/include/mach/sysmmu.h
create mode 100644 arch/arm/plat-s5p/dev-fimc3.c
create mode 100644 arch/arm/plat-s5p/include/plat/sysmmu.h
rewrite arch/arm/plat-s5p/sysmmu.c (85%)
create mode 100644 drivers/media/video/s5p-fimc/fimc-mem.h
create mode 100644 drivers/media/video/videobuf2-s5p-iommu.c
create mode 100644 include/media/videobuf2-s5p-iommu.h
--
1.7.1.569.g6f426
^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH 1/7] ARM: S5PV310: Add platform definitions for FIMC
2011-03-04 9:01 [PATCH/RFC 0/7] Samsung IOMMU videobuf2 allocator and s5p-fimc update Marek Szyprowski
@ 2011-03-04 9:01 ` Marek Szyprowski
2011-03-12 0:27 ` Kukjin Kim
2011-03-04 9:01 ` [PATCH 2/7] ARM: S5PV310: power domains: fixes and code cleanup Marek Szyprowski
` (6 subsequent siblings)
7 siblings, 1 reply; 29+ messages in thread
From: Marek Szyprowski @ 2011-03-04 9:01 UTC (permalink / raw)
To: linux-arm-kernel
From: Sylwester Nawrocki <s.nawrocki@samsung.com>
Add support for fourth FIMC platform device definition and define
resources for FIMC modules on S5PV310 machines.
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
arch/arm/mach-s5pv310/cpu.c | 7 ++++
arch/arm/mach-s5pv310/include/mach/irqs.h | 4 ++
arch/arm/mach-s5pv310/include/mach/map.h | 8 ++++
arch/arm/plat-s5p/Kconfig | 5 +++
arch/arm/plat-s5p/Makefile | 1 +
arch/arm/plat-s5p/dev-fimc3.c | 43 ++++++++++++++++++++++++
arch/arm/plat-samsung/include/plat/devs.h | 1 +
arch/arm/plat-samsung/include/plat/fimc-core.h | 5 +++
8 files changed, 74 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/plat-s5p/dev-fimc3.c
diff --git a/arch/arm/mach-s5pv310/cpu.c b/arch/arm/mach-s5pv310/cpu.c
index 0db0fb6..0bdb0b0 100644
--- a/arch/arm/mach-s5pv310/cpu.c
+++ b/arch/arm/mach-s5pv310/cpu.c
@@ -21,6 +21,8 @@
#include <plat/clock.h>
#include <plat/s5pv310.h>
#include <plat/sdhci.h>
+#include <plat/devs.h>
+#include <plat/fimc-core.h>
#include <mach/regs-irq.h>
@@ -114,6 +116,11 @@ void __init s5pv310_map_io(void)
s5pv310_default_sdhci1();
s5pv310_default_sdhci2();
s5pv310_default_sdhci3();
+
+ s3c_fimc_setname(0, "s5pv310-fimc");
+ s3c_fimc_setname(1, "s5pv310-fimc");
+ s3c_fimc_setname(2, "s5pv310-fimc");
+ s3c_fimc_setname(3, "s5pv310-fimc");
}
void __init s5pv310_init_clocks(int xtal)
diff --git a/arch/arm/mach-s5pv310/include/mach/irqs.h b/arch/arm/mach-s5pv310/include/mach/irqs.h
index 536b0b5..0e99968 100644
--- a/arch/arm/mach-s5pv310/include/mach/irqs.h
+++ b/arch/arm/mach-s5pv310/include/mach/irqs.h
@@ -107,6 +107,10 @@
#define IRQ_MIPI_CSIS0 COMBINER_IRQ(30, 0)
#define IRQ_MIPI_CSIS1 COMBINER_IRQ(30, 1)
+#define IRQ_FIMC0 COMBINER_IRQ(32, 0)
+#define IRQ_FIMC1 COMBINER_IRQ(32, 1)
+#define IRQ_FIMC2 COMBINER_IRQ(33, 0)
+#define IRQ_FIMC3 COMBINER_IRQ(33, 1)
#define IRQ_ONENAND_AUDI COMBINER_IRQ(34, 0)
diff --git a/arch/arm/mach-s5pv310/include/mach/map.h b/arch/arm/mach-s5pv310/include/mach/map.h
index 901657f..0db3a47 100644
--- a/arch/arm/mach-s5pv310/include/mach/map.h
+++ b/arch/arm/mach-s5pv310/include/mach/map.h
@@ -25,6 +25,10 @@
#define S5PV310_PA_SYSRAM 0x02025000
+#define S5PV310_PA_FIMC0 0x11800000
+#define S5PV310_PA_FIMC1 0x11810000
+#define S5PV310_PA_FIMC2 0x11820000
+#define S5PV310_PA_FIMC3 0x11830000
#define S5PV310_PA_I2S0 0x03830000
#define S5PV310_PA_I2S1 0xE3100000
#define S5PV310_PA_I2S2 0xE2A00000
@@ -121,6 +125,10 @@
#define S5P_PA_CHIPID S5PV310_PA_CHIPID
#define S5P_PA_MIPI_CSIS0 S5PV310_PA_MIPI_CSIS0
#define S5P_PA_MIPI_CSIS1 S5PV310_PA_MIPI_CSIS1
+#define S5P_PA_FIMC0 S5PV310_PA_FIMC0
+#define S5P_PA_FIMC1 S5PV310_PA_FIMC1
+#define S5P_PA_FIMC2 S5PV310_PA_FIMC2
+#define S5P_PA_FIMC3 S5PV310_PA_FIMC3
#define S5P_PA_ONENAND S5PC210_PA_ONENAND
#define S5P_PA_ONENAND_DMA S5PC210_PA_ONENAND_DMA
#define S5P_PA_SDRAM S5PV310_PA_SDRAM
diff --git a/arch/arm/plat-s5p/Kconfig b/arch/arm/plat-s5p/Kconfig
index 557f8c5..0db2a7a 100644
--- a/arch/arm/plat-s5p/Kconfig
+++ b/arch/arm/plat-s5p/Kconfig
@@ -60,6 +60,11 @@ config S5P_DEV_FIMC2
help
Compile in platform device definitions for FIMC controller 2
+config S5P_DEV_FIMC3
+ bool
+ help
+ Compile in platform device definitions for FIMC controller 3
+
config S5P_DEV_ONENAND
bool
help
diff --git a/arch/arm/plat-s5p/Makefile b/arch/arm/plat-s5p/Makefile
index ce5a0a7..cfcd1db 100644
--- a/arch/arm/plat-s5p/Makefile
+++ b/arch/arm/plat-s5p/Makefile
@@ -28,6 +28,7 @@ obj-$(CONFIG_SUSPEND) += irq-pm.o
obj-$(CONFIG_S5P_DEV_FIMC0) += dev-fimc0.o
obj-$(CONFIG_S5P_DEV_FIMC1) += dev-fimc1.o
obj-$(CONFIG_S5P_DEV_FIMC2) += dev-fimc2.o
+obj-$(CONFIG_S5P_DEV_FIMC3) += dev-fimc3.o
obj-$(CONFIG_S5P_DEV_ONENAND) += dev-onenand.o
obj-$(CONFIG_S5P_DEV_CSIS0) += dev-csis0.o
obj-$(CONFIG_S5P_DEV_CSIS1) += dev-csis1.o
diff --git a/arch/arm/plat-s5p/dev-fimc3.c b/arch/arm/plat-s5p/dev-fimc3.c
new file mode 100644
index 0000000..ef31bec
--- /dev/null
+++ b/arch/arm/plat-s5p/dev-fimc3.c
@@ -0,0 +1,43 @@
+/* linux/arch/arm/plat-s5p/dev-fimc3.c
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ *
+ * Base S5P FIMC3 resource and device definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <mach/map.h>
+
+static struct resource s5p_fimc3_resource[] = {
+ [0] = {
+ .start = S5P_PA_FIMC3,
+ .end = S5P_PA_FIMC3 + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_FIMC3,
+ .end = IRQ_FIMC3,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static u64 s5p_fimc3_dma_mask = DMA_BIT_MASK(32);
+
+struct platform_device s5p_device_fimc3 = {
+ .name = "s5p-fimc",
+ .id = 3,
+ .num_resources = ARRAY_SIZE(s5p_fimc3_resource),
+ .resource = s5p_fimc3_resource,
+ .dev = {
+ .dma_mask = &s5p_fimc3_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h
index b4d208b..b0123f3 100644
--- a/arch/arm/plat-samsung/include/plat/devs.h
+++ b/arch/arm/plat-samsung/include/plat/devs.h
@@ -133,6 +133,7 @@ extern struct platform_device samsung_device_keypad;
extern struct platform_device s5p_device_fimc0;
extern struct platform_device s5p_device_fimc1;
extern struct platform_device s5p_device_fimc2;
+extern struct platform_device s5p_device_fimc3;
extern struct platform_device s5p_device_mipi_csis0;
extern struct platform_device s5p_device_mipi_csis1;
diff --git a/arch/arm/plat-samsung/include/plat/fimc-core.h b/arch/arm/plat-samsung/include/plat/fimc-core.h
index 81a3bfe..945a99d 100644
--- a/arch/arm/plat-samsung/include/plat/fimc-core.h
+++ b/arch/arm/plat-samsung/include/plat/fimc-core.h
@@ -38,6 +38,11 @@ static inline void s3c_fimc_setname(int id, char *name)
s5p_device_fimc2.name = name;
break;
#endif
+#ifdef CONFIG_S5P_DEV_FIMC3
+ case 3:
+ s5p_device_fimc3.name = name;
+ break;
+#endif
}
}
--
1.7.1.569.g6f426
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH 2/7] ARM: S5PV310: power domains: fixes and code cleanup
2011-03-04 9:01 [PATCH/RFC 0/7] Samsung IOMMU videobuf2 allocator and s5p-fimc update Marek Szyprowski
2011-03-04 9:01 ` [PATCH 1/7] ARM: S5PV310: Add platform definitions for FIMC Marek Szyprowski
@ 2011-03-04 9:01 ` Marek Szyprowski
2011-03-04 9:01 ` [PATCH 3/7] ARM: Samsung: update/rewrite Samsung SYSMMU (IOMMU) driver Marek Szyprowski
` (5 subsequent siblings)
7 siblings, 0 replies; 29+ messages in thread
From: Marek Szyprowski @ 2011-03-04 9:01 UTC (permalink / raw)
To: linux-arm-kernel
From: Tomasz Stanislawski <t.stanislaws@samsung.com>
This patch extends power domain driver with support for enabling and
disabling modules in S5P_CLKGATE_BLOCK register. It also performs a
little code cleanup to avoid confusion between s5pv310_device_pd array
index and power domain id.
Signed-off-by: Tomasz Stanislawski <t.stanislaws@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
arch/arm/mach-s5pv310/dev-pd.c | 93 +++++++++++++++++------
arch/arm/mach-s5pv310/include/mach/regs-clock.h | 9 ++
arch/arm/plat-samsung/include/plat/pd.h | 1 +
3 files changed, 81 insertions(+), 22 deletions(-)
diff --git a/arch/arm/mach-s5pv310/dev-pd.c b/arch/arm/mach-s5pv310/dev-pd.c
index 58a50c2..e051998 100644
--- a/arch/arm/mach-s5pv310/dev-pd.c
+++ b/arch/arm/mach-s5pv310/dev-pd.c
@@ -16,13 +16,17 @@
#include <linux/delay.h>
#include <mach/regs-pmu.h>
+#include <mach/regs-clock.h>
#include <plat/pd.h>
+static spinlock_t gate_block_slock = SPIN_LOCK_UNLOCKED;
+
static int s5pv310_pd_enable(struct device *dev)
{
struct samsung_pd_info *pdata = dev->platform_data;
u32 timeout;
+ int ret = 0;
__raw_writel(S5P_INT_LOCAL_PWR_EN, pdata->base);
@@ -31,21 +35,39 @@ static int s5pv310_pd_enable(struct device *dev)
while ((__raw_readl(pdata->base + 0x4) & S5P_INT_LOCAL_PWR_EN)
!= S5P_INT_LOCAL_PWR_EN) {
if (timeout == 0) {
- printk(KERN_ERR "Power domain %s enable failed.\n",
- dev_name(dev));
- return -ETIMEDOUT;
+ dev_err(dev, "enable failed\n");
+ ret = -ETIMEDOUT;
+ goto done;
}
timeout--;
udelay(100);
}
- return 0;
+ /* configure clk gate mask if it is present */
+ if (pdata->gate_mask) {
+ unsigned long flags;
+ unsigned long value;
+
+ spin_lock_irqsave(&gate_block_slock, flags);
+
+ value = __raw_readl(S5P_CLKGATE_BLOCK);
+ value |= pdata->gate_mask;
+ __raw_writel(value, S5P_CLKGATE_BLOCK);
+
+ spin_unlock_irqrestore(&gate_block_slock, flags);
+ }
+
+done:
+ dev_info(dev, "enable finished\n");
+
+ return ret;
}
static int s5pv310_pd_disable(struct device *dev)
{
struct samsung_pd_info *pdata = dev->platform_data;
u32 timeout;
+ int ret = 0;
__raw_writel(0, pdata->base);
@@ -53,81 +75,108 @@ static int s5pv310_pd_disable(struct device *dev)
timeout = 10;
while (__raw_readl(pdata->base + 0x4) & S5P_INT_LOCAL_PWR_EN) {
if (timeout == 0) {
- printk(KERN_ERR "Power domain %s disable failed.\n",
- dev_name(dev));
- return -ETIMEDOUT;
+ dev_err(dev, "disable failed\n");
+ ret = -ETIMEDOUT;
+ goto done;
}
timeout--;
udelay(100);
}
- return 0;
+ if (pdata->gate_mask) {
+ unsigned long flags;
+ unsigned long value;
+
+ spin_lock_irqsave(&gate_block_slock, flags);
+
+ value = __raw_readl(S5P_CLKGATE_BLOCK);
+ value &= ~pdata->gate_mask;
+ __raw_writel(value, S5P_CLKGATE_BLOCK);
+
+ spin_unlock_irqrestore(&gate_block_slock, flags);
+ }
+done:
+ dev_info(dev, "disable finished\n");
+
+ return ret;
}
struct platform_device s5pv310_device_pd[] = {
- {
+ [PD_MFC] = {
.name = "samsung-pd",
- .id = 0,
+ .id = PD_MFC,
.dev = {
.platform_data = &(struct samsung_pd_info) {
.enable = s5pv310_pd_enable,
.disable = s5pv310_pd_disable,
.base = S5P_PMU_MFC_CONF,
+ .gate_mask = S5P_CLKGATE_BLOCK_MFC,
},
},
- }, {
+ },
+ [PD_G3D] = {
.name = "samsung-pd",
- .id = 1,
+ .id = PD_G3D,
.dev = {
.platform_data = &(struct samsung_pd_info) {
.enable = s5pv310_pd_enable,
.disable = s5pv310_pd_disable,
.base = S5P_PMU_G3D_CONF,
+ .gate_mask = S5P_CLKGATE_BLOCK_G3D,
},
},
- }, {
+ },
+ [PD_LCD0] = {
.name = "samsung-pd",
- .id = 2,
+ .id = PD_LCD0,
.dev = {
.platform_data = &(struct samsung_pd_info) {
.enable = s5pv310_pd_enable,
.disable = s5pv310_pd_disable,
.base = S5P_PMU_LCD0_CONF,
+ .gate_mask = S5P_CLKGATE_BLOCK_LCD0,
},
},
- }, {
+ },
+ [PD_LCD1] = {
.name = "samsung-pd",
- .id = 3,
+ .id = PD_LCD1,
.dev = {
.platform_data = &(struct samsung_pd_info) {
.enable = s5pv310_pd_enable,
.disable = s5pv310_pd_disable,
.base = S5P_PMU_LCD1_CONF,
+ .gate_mask = S5P_CLKGATE_BLOCK_LCD1,
},
},
- }, {
+ },
+ [PD_TV] = {
.name = "samsung-pd",
- .id = 4,
+ .id = PD_TV,
.dev = {
.platform_data = &(struct samsung_pd_info) {
.enable = s5pv310_pd_enable,
.disable = s5pv310_pd_disable,
.base = S5P_PMU_TV_CONF,
+ .gate_mask = S5P_CLKGATE_BLOCK_TV,
},
},
- }, {
+ },
+ [PD_CAM] = {
.name = "samsung-pd",
- .id = 5,
+ .id = PD_CAM,
.dev = {
.platform_data = &(struct samsung_pd_info) {
.enable = s5pv310_pd_enable,
.disable = s5pv310_pd_disable,
.base = S5P_PMU_CAM_CONF,
+ .gate_mask = S5P_CLKGATE_BLOCK_CAM,
},
},
- }, {
+ },
+ [PD_GPS] = {
.name = "samsung-pd",
- .id = 6,
+ .id = PD_GPS,
.dev = {
.platform_data = &(struct samsung_pd_info) {
.enable = s5pv310_pd_enable,
diff --git a/arch/arm/mach-s5pv310/include/mach/regs-clock.h b/arch/arm/mach-s5pv310/include/mach/regs-clock.h
index b5c4ada..341571a 100644
--- a/arch/arm/mach-s5pv310/include/mach/regs-clock.h
+++ b/arch/arm/mach-s5pv310/include/mach/regs-clock.h
@@ -73,6 +73,7 @@
#define S5P_CLKGATE_IP_FSYS S5P_CLKREG(0x0C940)
#define S5P_CLKGATE_IP_PERIL S5P_CLKREG(0x0C950)
#define S5P_CLKGATE_IP_PERIR S5P_CLKREG(0x0C960)
+#define S5P_CLKGATE_BLOCK S5P_CLKREG(0x0C970)
#define S5P_CLKSRC_DMC S5P_CLKREG(0x10200)
#define S5P_CLKDIV_DMC0 S5P_CLKREG(0x10500)
@@ -160,6 +161,14 @@
#define S5P_CLKDIV_BUS_GPLR_SHIFT (4)
#define S5P_CLKDIV_BUS_GPLR_MASK (0x7 << S5P_CLKDIV_BUS_GPLR_SHIFT)
+/* CLKGATE_BLOCK */
+#define S5P_CLKGATE_BLOCK_CAM (1 << 0)
+#define S5P_CLKGATE_BLOCK_TV (1 << 1)
+#define S5P_CLKGATE_BLOCK_MFC (1 << 2)
+#define S5P_CLKGATE_BLOCK_G3D (1 << 3)
+#define S5P_CLKGATE_BLOCK_LCD0 (1 << 4)
+#define S5P_CLKGATE_BLOCK_LCD1 (1 << 5)
+
/* Compatibility defines */
#define S5P_EPLL_CON S5P_EPLL_CON0
diff --git a/arch/arm/plat-samsung/include/plat/pd.h b/arch/arm/plat-samsung/include/plat/pd.h
index 5f0ad85..36ba851 100644
--- a/arch/arm/plat-samsung/include/plat/pd.h
+++ b/arch/arm/plat-samsung/include/plat/pd.h
@@ -15,6 +15,7 @@ struct samsung_pd_info {
int (*enable)(struct device *dev);
int (*disable)(struct device *dev);
void __iomem *base;
+ unsigned long gate_mask;
};
enum s5pv310_pd_block {
--
1.7.1.569.g6f426
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH 3/7] ARM: Samsung: update/rewrite Samsung SYSMMU (IOMMU) driver
2011-03-04 9:01 [PATCH/RFC 0/7] Samsung IOMMU videobuf2 allocator and s5p-fimc update Marek Szyprowski
2011-03-04 9:01 ` [PATCH 1/7] ARM: S5PV310: Add platform definitions for FIMC Marek Szyprowski
2011-03-04 9:01 ` [PATCH 2/7] ARM: S5PV310: power domains: fixes and code cleanup Marek Szyprowski
@ 2011-03-04 9:01 ` Marek Szyprowski
2011-03-04 16:04 ` Marek Szyprowski
2011-03-04 9:01 ` [PATCH 4/7] v4l: videobuf2: add Samsung SYSMMU (IOMMU) based allocator Marek Szyprowski
` (4 subsequent siblings)
7 siblings, 1 reply; 29+ messages in thread
From: Marek Szyprowski @ 2011-03-04 9:01 UTC (permalink / raw)
To: linux-arm-kernel
From: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
This patch performs a complete rewrite of sysmmu driver for Samsung platform:
- the new version introduces an api to construct device private page
tables and enables to use device private address space mode
- simplified the resource management: no more single platform
device with 32 resources is needed, better fits into linux driver model,
each sysmmu instance has it's own resource definition
- added support for sysmmu clocks
- some other minor API chages required by upcoming videobuf2 allocator
Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
arch/arm/mach-s5pv310/clock.c | 91 ++
arch/arm/mach-s5pv310/dev-sysmmu.c | 582 +++++++++----
arch/arm/mach-s5pv310/include/mach/irqs.h | 36 +-
arch/arm/mach-s5pv310/include/mach/regs-clock.h | 3 +
arch/arm/mach-s5pv310/include/mach/regs-sysmmu.h | 23 +-
arch/arm/mach-s5pv310/include/mach/sysmmu.h | 122 ---
arch/arm/plat-s5p/Kconfig | 17 +-
arch/arm/plat-s5p/include/plat/sysmmu.h | 127 +++
arch/arm/plat-s5p/sysmmu.c | 988 +++++++++++++++-------
arch/arm/plat-samsung/include/plat/devs.h | 2 +-
10 files changed, 1323 insertions(+), 668 deletions(-)
rewrite arch/arm/mach-s5pv310/dev-sysmmu.c (86%)
delete mode 100644 arch/arm/mach-s5pv310/include/mach/sysmmu.h
create mode 100644 arch/arm/plat-s5p/include/plat/sysmmu.h
rewrite arch/arm/plat-s5p/sysmmu.c (85%)
diff --git a/arch/arm/mach-s5pv310/clock.c b/arch/arm/mach-s5pv310/clock.c
index fc7c2f8..f142b8c 100644
--- a/arch/arm/mach-s5pv310/clock.c
+++ b/arch/arm/mach-s5pv310/clock.c
@@ -20,6 +20,7 @@
#include <plat/pll.h>
#include <plat/s5p-clock.h>
#include <plat/clock-clksrc.h>
+#include <plat/sysmmu.h>
#include <mach/map.h>
#include <mach/regs-clock.h>
@@ -116,6 +117,21 @@ static int s5pv310_clk_ip_perir_ctrl(struct clk *clk, int enable)
return s5p_gatectrl(S5P_CLKGATE_IP_PERIR, clk, enable);
}
+static int s5pv310_clk_ip_dmc_ctrl(struct clk *clk, int enable)
+{
+ return s5p_gatectrl(S5P_CLKGATE_IP_DMC, clk, enable);
+}
+
+static int s5pv310_clk_ip_mfc_ctrl(struct clk *clk, int enable)
+{
+ return s5p_gatectrl(S5P_CLKGATE_IP_MFC, clk, enable);
+}
+
+static int s5pv310_clk_ip_tv_ctrl(struct clk *clk, int enable)
+{
+ return s5p_gatectrl(S5P_CLKGATE_IP_TV, clk, enable);
+}
+
/* Core list of CMU_CPU side */
static struct clksrc_clk clk_mout_apll = {
@@ -422,6 +438,81 @@ static struct clk init_clocks_off[] = {
.enable = s5pv310_clk_ip_cam_ctrl,
.ctrlbit = (1 << 3),
}, {
+ .name = "sysmmu",
+ .id = S5P_SYSMMU_MFC_L,
+ .enable = s5pv310_clk_ip_mfc_ctrl,
+ .ctrlbit = ((15 << 1) | 1),
+ }, {
+ .name = "sysmmu",
+ .id = S5P_SYSMMU_MFC_R,
+ .enable = s5pv310_clk_ip_mfc_ctrl,
+ .ctrlbit = ((15 << 1) | 1),
+ }, {
+ .name = "sysmmu",
+ .id = S5P_SYSMMU_FIMC0,
+ .enable = s5pv310_clk_ip_cam_ctrl,
+ .ctrlbit = (1 << 7),
+ }, {
+ .name = "sysmmu",
+ .id = S5P_SYSMMU_FIMC1,
+ .enable = s5pv310_clk_ip_cam_ctrl,
+ .ctrlbit = (1 << 8),
+ } , {
+ .name = "sysmmu",
+ .id = S5P_SYSMMU_FIMC2,
+ .enable = s5pv310_clk_ip_cam_ctrl,
+ .ctrlbit = (1 << 9),
+ } , {
+ .name = "sysmmu",
+ .id = S5P_SYSMMU_FIMC3,
+ .enable = s5pv310_clk_ip_cam_ctrl,
+ .ctrlbit = (1 << 10),
+ } , {
+ .name = "sysmmu",
+ .id = S5P_SYSMMU_JPEG,
+ .enable = s5pv310_clk_ip_cam_ctrl,
+ .ctrlbit = (1 << 11),
+ } , {
+ .name = "sysmmu",
+ .id = S5P_SYSMMU_TV,
+ .enable = s5pv310_clk_ip_tv_ctrl,
+ .ctrlbit = (1 << 4),
+ } , {
+ .name = "sysmmu",
+ .id = S5P_SYSMMU_G2D,
+ .enable = s5pv310_clk_ip_image_ctrl,
+ .ctrlbit = (1 << 3),
+ } , {
+ .name = "sysmmu",
+ .id = S5P_SYSMMU_ROTATOR,
+ .enable = s5pv310_clk_ip_image_ctrl,
+ .ctrlbit = (1 << 4),
+ } , {
+ .name = "sysmmu",
+ .id = S5P_SYSMMU_MDMA,
+ .enable = s5pv310_clk_ip_image_ctrl,
+ .ctrlbit = (1 << 5),
+ } , {
+ .name = "sysmmu",
+ .id = S5P_SYSMMU_FIMD0,
+ .enable = s5pv310_clk_ip_lcd0_ctrl,
+ .ctrlbit = (1 << 4),
+ } , {
+ .name = "sysmmu",
+ .id = S5P_SYSMMU_FIMD1,
+ .enable = s5pv310_clk_ip_lcd1_ctrl,
+ .ctrlbit = (1 << 4),
+ } , {
+ .name = "sysmmu",
+ .id = S5P_SYSMMU_PCIe,
+ .enable = s5pv310_clk_ip_fsys_ctrl,
+ .ctrlbit = (1 << 18),
+ } , {
+ .name = "sysmmu",
+ .id = S5P_SYSMMU_SSS,
+ .enable = s5pv310_clk_ip_dmc_ctrl,
+ .ctrlbit = (1 << 12),
+ } , {
.name = "fimd",
.id = 0,
.enable = s5pv310_clk_ip_lcd0_ctrl,
diff --git a/arch/arm/mach-s5pv310/dev-sysmmu.c b/arch/arm/mach-s5pv310/dev-sysmmu.c
dissimilarity index 86%
index e1bb200..73c1541 100644
--- a/arch/arm/mach-s5pv310/dev-sysmmu.c
+++ b/arch/arm/mach-s5pv310/dev-sysmmu.c
@@ -1,187 +1,395 @@
-/* linux/arch/arm/mach-s5pv310/dev-sysmmu.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-
-#include <mach/map.h>
-#include <mach/irqs.h>
-
-static struct resource s5pv310_sysmmu_resource[] = {
- [0] = {
- .start = S5PV310_PA_SYSMMU_MDMA,
- .end = S5PV310_PA_SYSMMU_MDMA + SZ_64K - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = IRQ_SYSMMU_MDMA0_0,
- .end = IRQ_SYSMMU_MDMA0_0,
- .flags = IORESOURCE_IRQ,
- },
- [2] = {
- .start = S5PV310_PA_SYSMMU_SSS,
- .end = S5PV310_PA_SYSMMU_SSS + SZ_64K - 1,
- .flags = IORESOURCE_MEM,
- },
- [3] = {
- .start = IRQ_SYSMMU_SSS_0,
- .end = IRQ_SYSMMU_SSS_0,
- .flags = IORESOURCE_IRQ,
- },
- [4] = {
- .start = S5PV310_PA_SYSMMU_FIMC0,
- .end = S5PV310_PA_SYSMMU_FIMC0 + SZ_64K - 1,
- .flags = IORESOURCE_MEM,
- },
- [5] = {
- .start = IRQ_SYSMMU_FIMC0_0,
- .end = IRQ_SYSMMU_FIMC0_0,
- .flags = IORESOURCE_IRQ,
- },
- [6] = {
- .start = S5PV310_PA_SYSMMU_FIMC1,
- .end = S5PV310_PA_SYSMMU_FIMC1 + SZ_64K - 1,
- .flags = IORESOURCE_MEM,
- },
- [7] = {
- .start = IRQ_SYSMMU_FIMC1_0,
- .end = IRQ_SYSMMU_FIMC1_0,
- .flags = IORESOURCE_IRQ,
- },
- [8] = {
- .start = S5PV310_PA_SYSMMU_FIMC2,
- .end = S5PV310_PA_SYSMMU_FIMC2 + SZ_64K - 1,
- .flags = IORESOURCE_MEM,
- },
- [9] = {
- .start = IRQ_SYSMMU_FIMC2_0,
- .end = IRQ_SYSMMU_FIMC2_0,
- .flags = IORESOURCE_IRQ,
- },
- [10] = {
- .start = S5PV310_PA_SYSMMU_FIMC3,
- .end = S5PV310_PA_SYSMMU_FIMC3 + SZ_64K - 1,
- .flags = IORESOURCE_MEM,
- },
- [11] = {
- .start = IRQ_SYSMMU_FIMC3_0,
- .end = IRQ_SYSMMU_FIMC3_0,
- .flags = IORESOURCE_IRQ,
- },
- [12] = {
- .start = S5PV310_PA_SYSMMU_JPEG,
- .end = S5PV310_PA_SYSMMU_JPEG + SZ_64K - 1,
- .flags = IORESOURCE_MEM,
- },
- [13] = {
- .start = IRQ_SYSMMU_JPEG_0,
- .end = IRQ_SYSMMU_JPEG_0,
- .flags = IORESOURCE_IRQ,
- },
- [14] = {
- .start = S5PV310_PA_SYSMMU_FIMD0,
- .end = S5PV310_PA_SYSMMU_FIMD0 + SZ_64K - 1,
- .flags = IORESOURCE_MEM,
- },
- [15] = {
- .start = IRQ_SYSMMU_LCD0_M0_0,
- .end = IRQ_SYSMMU_LCD0_M0_0,
- .flags = IORESOURCE_IRQ,
- },
- [16] = {
- .start = S5PV310_PA_SYSMMU_FIMD1,
- .end = S5PV310_PA_SYSMMU_FIMD1 + SZ_64K - 1,
- .flags = IORESOURCE_MEM,
- },
- [17] = {
- .start = IRQ_SYSMMU_LCD1_M1_0,
- .end = IRQ_SYSMMU_LCD1_M1_0,
- .flags = IORESOURCE_IRQ,
- },
- [18] = {
- .start = S5PV310_PA_SYSMMU_PCIe,
- .end = S5PV310_PA_SYSMMU_PCIe + SZ_64K - 1,
- .flags = IORESOURCE_MEM,
- },
- [19] = {
- .start = IRQ_SYSMMU_PCIE_0,
- .end = IRQ_SYSMMU_PCIE_0,
- .flags = IORESOURCE_IRQ,
- },
- [20] = {
- .start = S5PV310_PA_SYSMMU_G2D,
- .end = S5PV310_PA_SYSMMU_G2D + SZ_64K - 1,
- .flags = IORESOURCE_MEM,
- },
- [21] = {
- .start = IRQ_SYSMMU_2D_0,
- .end = IRQ_SYSMMU_2D_0,
- .flags = IORESOURCE_IRQ,
- },
- [22] = {
- .start = S5PV310_PA_SYSMMU_ROTATOR,
- .end = S5PV310_PA_SYSMMU_ROTATOR + SZ_64K - 1,
- .flags = IORESOURCE_MEM,
- },
- [23] = {
- .start = IRQ_SYSMMU_ROTATOR_0,
- .end = IRQ_SYSMMU_ROTATOR_0,
- .flags = IORESOURCE_IRQ,
- },
- [24] = {
- .start = S5PV310_PA_SYSMMU_MDMA2,
- .end = S5PV310_PA_SYSMMU_MDMA2 + SZ_64K - 1,
- .flags = IORESOURCE_MEM,
- },
- [25] = {
- .start = IRQ_SYSMMU_MDMA1_0,
- .end = IRQ_SYSMMU_MDMA1_0,
- .flags = IORESOURCE_IRQ,
- },
- [26] = {
- .start = S5PV310_PA_SYSMMU_TV,
- .end = S5PV310_PA_SYSMMU_TV + SZ_64K - 1,
- .flags = IORESOURCE_MEM,
- },
- [27] = {
- .start = IRQ_SYSMMU_TV_M0_0,
- .end = IRQ_SYSMMU_TV_M0_0,
- .flags = IORESOURCE_IRQ,
- },
- [28] = {
- .start = S5PV310_PA_SYSMMU_MFC_L,
- .end = S5PV310_PA_SYSMMU_MFC_L + SZ_64K - 1,
- .flags = IORESOURCE_MEM,
- },
- [29] = {
- .start = IRQ_SYSMMU_MFC_M0_0,
- .end = IRQ_SYSMMU_MFC_M0_0,
- .flags = IORESOURCE_IRQ,
- },
- [30] = {
- .start = S5PV310_PA_SYSMMU_MFC_R,
- .end = S5PV310_PA_SYSMMU_MFC_R + SZ_64K - 1,
- .flags = IORESOURCE_MEM,
- },
- [31] = {
- .start = IRQ_SYSMMU_MFC_M1_0,
- .end = IRQ_SYSMMU_MFC_M1_0,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-struct platform_device s5pv310_device_sysmmu = {
- .name = "s5p-sysmmu",
- .id = 32,
- .num_resources = ARRAY_SIZE(s5pv310_sysmmu_resource),
- .resource = s5pv310_sysmmu_resource,
-};
-
-EXPORT_SYMBOL(s5pv310_device_sysmmu);
+/* linux/arch/arm/mach-s5pv310/dev-sysmmu.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+
+#include <mach/map.h>
+#include <mach/irqs.h>
+
+#include <plat/devs.h>
+#include <plat/cpu.h>
+#include <plat/sysmmu.h>
+
+static struct resource s5p_sysmmu_resource[][2] = {
+ [S5P_SYSMMU_MDMA] = {
+ [0] = {
+ .start = S5PV310_PA_SYSMMU_MDMA,
+ .end = S5PV310_PA_SYSMMU_MDMA + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_SYSMMU_MDMA0,
+ .end = IRQ_SYSMMU_MDMA0,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ [S5P_SYSMMU_SSS] = {
+ [0] = {
+ .start = S5PV310_PA_SYSMMU_SSS,
+ .end = S5PV310_PA_SYSMMU_SSS + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_SYSMMU_SSS,
+ .end = IRQ_SYSMMU_SSS,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ [S5P_SYSMMU_FIMC0] = {
+ [0] = {
+ .start = S5PV310_PA_SYSMMU_FIMC0,
+ .end = S5PV310_PA_SYSMMU_FIMC0 + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_SYSMMU_FIMC0,
+ .end = IRQ_SYSMMU_FIMC0,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ [S5P_SYSMMU_FIMC1] = {
+ [0] = {
+ .start = S5PV310_PA_SYSMMU_FIMC1,
+ .end = S5PV310_PA_SYSMMU_FIMC1 + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_SYSMMU_FIMC1,
+ .end = IRQ_SYSMMU_FIMC1,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ [S5P_SYSMMU_FIMC2] = {
+ [0] = {
+ .start = S5PV310_PA_SYSMMU_FIMC2,
+ .end = S5PV310_PA_SYSMMU_FIMC2 + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_SYSMMU_FIMC2,
+ .end = IRQ_SYSMMU_FIMC2,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ [S5P_SYSMMU_FIMC3] = {
+ [0] = {
+ .start = S5PV310_PA_SYSMMU_FIMC3,
+ .end = S5PV310_PA_SYSMMU_FIMC3 + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_SYSMMU_FIMC3,
+ .end = IRQ_SYSMMU_FIMC3,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ [S5P_SYSMMU_JPEG] = {
+ [0] = {
+ .start = S5PV310_PA_SYSMMU_JPEG,
+ .end = S5PV310_PA_SYSMMU_JPEG + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_SYSMMU_JPEG,
+ .end = IRQ_SYSMMU_JPEG,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ [S5P_SYSMMU_FIMD0] = {
+ [0] = {
+ .start = S5PV310_PA_SYSMMU_FIMD0,
+ .end = S5PV310_PA_SYSMMU_FIMD0 + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_SYSMMU_FIMD0,
+ .end = IRQ_SYSMMU_FIMD0,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ [S5P_SYSMMU_FIMD1] = {
+ [0] = {
+ .start = S5PV310_PA_SYSMMU_FIMD1,
+ .end = S5PV310_PA_SYSMMU_FIMD1 + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_SYSMMU_FIMD1,
+ .end = IRQ_SYSMMU_FIMD1,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ [S5P_SYSMMU_PCIe] = {
+ [0] = {
+ .start = S5PV310_PA_SYSMMU_PCIe,
+ .end = S5PV310_PA_SYSMMU_PCIe + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_SYSMMU_PCIE,
+ .end = IRQ_SYSMMU_PCIE,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ [S5P_SYSMMU_G2D] = {
+ [0] = {
+ .start = S5PV310_PA_SYSMMU_G2D,
+ .end = S5PV310_PA_SYSMMU_G2D + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_SYSMMU_2D,
+ .end = IRQ_SYSMMU_2D,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ [S5P_SYSMMU_ROTATOR] = {
+ [0] = {
+ .start = S5PV310_PA_SYSMMU_ROTATOR,
+ .end = S5PV310_PA_SYSMMU_ROTATOR + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_SYSMMU_ROTATOR,
+ .end = IRQ_SYSMMU_ROTATOR,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ [S5P_SYSMMU_MDMA2] = {
+ [0] = {
+ .start = S5PV310_PA_SYSMMU_MDMA2,
+ .end = S5PV310_PA_SYSMMU_MDMA2 + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_SYSMMU_MDMA1,
+ .end = IRQ_SYSMMU_MDMA1,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ [S5P_SYSMMU_TV] = {
+ [0] = {
+ .start = S5PV310_PA_SYSMMU_TV,
+ .end = S5PV310_PA_SYSMMU_TV + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_SYSMMU_TV,
+ .end = IRQ_SYSMMU_TV,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ [S5P_SYSMMU_MFC_L] = {
+ [0] = {
+ .start = S5PV310_PA_SYSMMU_MFC_L,
+ .end = S5PV310_PA_SYSMMU_MFC_L + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_SYSMMU_MFC_L,
+ .end = IRQ_SYSMMU_MFC_L,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ [S5P_SYSMMU_MFC_R] = {
+ [0] = {
+ .start = S5PV310_PA_SYSMMU_MFC_R,
+ .end = S5PV310_PA_SYSMMU_MFC_R + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_SYSMMU_MFC_R,
+ .end = IRQ_SYSMMU_MFC_R,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+};
+
+static u64 s5p_sysmmu_dma_mask = DMA_BIT_MASK(32);
+
+struct platform_device s5pv310_device_sysmmu[] = {
+ [S5P_SYSMMU_MDMA] = {
+ .name = "s5p-sysmmu",
+ .id = S5P_SYSMMU_MDMA,
+ .num_resources = ARRAY_SIZE(
+ s5p_sysmmu_resource[S5P_SYSMMU_MDMA]),
+ .resource = s5p_sysmmu_resource[S5P_SYSMMU_MDMA],
+ .dev = {
+ .dma_mask = &s5p_sysmmu_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ },
+ [S5P_SYSMMU_SSS] = {
+ .name = "s5p-sysmmu",
+ .id = S5P_SYSMMU_SSS,
+ .num_resources = ARRAY_SIZE(
+ s5p_sysmmu_resource[S5P_SYSMMU_SSS]),
+ .resource = s5p_sysmmu_resource[S5P_SYSMMU_SSS],
+ .dev = {
+ .dma_mask = &s5p_sysmmu_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ },
+ [S5P_SYSMMU_FIMC0] = {
+ .name = "s5p-sysmmu",
+ .id = S5P_SYSMMU_FIMC0,
+ .num_resources = ARRAY_SIZE(
+ s5p_sysmmu_resource[S5P_SYSMMU_FIMC0]),
+ .resource = s5p_sysmmu_resource[S5P_SYSMMU_FIMC0],
+ .dev = {
+ .dma_mask = &s5p_sysmmu_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ },
+ [S5P_SYSMMU_FIMC1] = {
+ .name = "s5p-sysmmu",
+ .id = S5P_SYSMMU_FIMC1,
+ .num_resources = ARRAY_SIZE(
+ s5p_sysmmu_resource[S5P_SYSMMU_FIMC1]),
+ .resource = s5p_sysmmu_resource[S5P_SYSMMU_FIMC1],
+ .dev = {
+ .dma_mask = &s5p_sysmmu_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ },
+ [S5P_SYSMMU_FIMC2] = {
+ .name = "s5p-sysmmu",
+ .id = S5P_SYSMMU_FIMC2,
+ .num_resources = ARRAY_SIZE(
+ s5p_sysmmu_resource[S5P_SYSMMU_FIMC2]),
+ .resource = s5p_sysmmu_resource[S5P_SYSMMU_FIMC2],
+ .dev = {
+ .dma_mask = &s5p_sysmmu_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ },
+ [S5P_SYSMMU_FIMC3] = {
+ .name = "s5p-sysmmu",
+ .id = S5P_SYSMMU_FIMC3,
+ .num_resources = ARRAY_SIZE(
+ s5p_sysmmu_resource[S5P_SYSMMU_FIMC3]),
+ .resource = s5p_sysmmu_resource[S5P_SYSMMU_FIMC3],
+ .dev = {
+ .dma_mask = &s5p_sysmmu_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ },
+ [S5P_SYSMMU_JPEG] = {
+ .name = "s5p-sysmmu",
+ .id = S5P_SYSMMU_JPEG,
+ .num_resources = ARRAY_SIZE(
+ s5p_sysmmu_resource[S5P_SYSMMU_JPEG]),
+ .resource = s5p_sysmmu_resource[S5P_SYSMMU_JPEG],
+ .dev = {
+ .dma_mask = &s5p_sysmmu_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ },
+ [S5P_SYSMMU_FIMD0] = {
+ .name = "s5p-sysmmu",
+ .id = S5P_SYSMMU_FIMD0,
+ .num_resources = ARRAY_SIZE(
+ s5p_sysmmu_resource[S5P_SYSMMU_FIMD0]),
+ .resource = s5p_sysmmu_resource[S5P_SYSMMU_FIMD0],
+ .dev = {
+ .dma_mask = &s5p_sysmmu_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ },
+ [S5P_SYSMMU_FIMD1] = {
+ .name = "s5p-sysmmu",
+ .id = S5P_SYSMMU_FIMD1,
+ .num_resources = ARRAY_SIZE(
+ s5p_sysmmu_resource[S5P_SYSMMU_FIMD1]),
+ .resource = s5p_sysmmu_resource[S5P_SYSMMU_FIMD1],
+ .dev = {
+ .dma_mask = &s5p_sysmmu_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ },
+ [S5P_SYSMMU_PCIe] = {
+ .name = "s5p-sysmmu",
+ .id = S5P_SYSMMU_PCIe,
+ .num_resources = ARRAY_SIZE(
+ s5p_sysmmu_resource[S5P_SYSMMU_PCIe]),
+ .resource = s5p_sysmmu_resource[S5P_SYSMMU_PCIe],
+ .dev = {
+ .dma_mask = &s5p_sysmmu_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ },
+ [S5P_SYSMMU_G2D] = {
+ .name = "s5p-sysmmu",
+ .id = S5P_SYSMMU_G2D,
+ .num_resources = ARRAY_SIZE(
+ s5p_sysmmu_resource[S5P_SYSMMU_G2D]),
+ .resource = s5p_sysmmu_resource[S5P_SYSMMU_G2D],
+ .dev = {
+ .dma_mask = &s5p_sysmmu_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ },
+ [S5P_SYSMMU_ROTATOR] = {
+ .name = "s5p-sysmmu",
+ .id = S5P_SYSMMU_ROTATOR,
+ .num_resources = ARRAY_SIZE(
+ s5p_sysmmu_resource[S5P_SYSMMU_ROTATOR]),
+ .resource = s5p_sysmmu_resource[S5P_SYSMMU_ROTATOR],
+ .dev = {
+ .dma_mask = &s5p_sysmmu_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ },
+ [S5P_SYSMMU_MDMA2] = {
+ .name = "s5p-sysmmu",
+ .id = S5P_SYSMMU_MDMA2,
+ .num_resources = ARRAY_SIZE(
+ s5p_sysmmu_resource[S5P_SYSMMU_MDMA2]),
+ .resource = s5p_sysmmu_resource[S5P_SYSMMU_MDMA2],
+ .dev = {
+ .dma_mask = &s5p_sysmmu_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ },
+ [S5P_SYSMMU_TV] = {
+ .name = "s5p-sysmmu",
+ .id = S5P_SYSMMU_TV,
+ .num_resources = ARRAY_SIZE(
+ s5p_sysmmu_resource[S5P_SYSMMU_TV]),
+ .resource = s5p_sysmmu_resource[S5P_SYSMMU_TV],
+ .dev = {
+ .dma_mask = &s5p_sysmmu_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ },
+ [S5P_SYSMMU_MFC_L] = {
+ .name = "s5p-sysmmu",
+ .id = S5P_SYSMMU_MFC_L,
+ .num_resources = ARRAY_SIZE(
+ s5p_sysmmu_resource[S5P_SYSMMU_MFC_L]),
+ .resource = s5p_sysmmu_resource[S5P_SYSMMU_MFC_L],
+ .dev = {
+ .dma_mask = &s5p_sysmmu_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ },
+ [S5P_SYSMMU_MFC_R] = {
+ .name = "s5p-sysmmu",
+ .id = S5P_SYSMMU_MFC_R,
+ .num_resources = ARRAY_SIZE(
+ s5p_sysmmu_resource[S5P_SYSMMU_MFC_R]),
+ .resource = s5p_sysmmu_resource[S5P_SYSMMU_MFC_R],
+ .dev = {
+ .dma_mask = &s5p_sysmmu_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ },
+};
diff --git a/arch/arm/mach-s5pv310/include/mach/irqs.h b/arch/arm/mach-s5pv310/include/mach/irqs.h
index 0e99968..f6b99c6 100644
--- a/arch/arm/mach-s5pv310/include/mach/irqs.h
+++ b/arch/arm/mach-s5pv310/include/mach/irqs.h
@@ -55,23 +55,24 @@
#define COMBINER_GROUP(x) ((x) * MAX_IRQ_IN_COMBINER + IRQ_SPI(64))
#define COMBINER_IRQ(x, y) (COMBINER_GROUP(x) + y)
-#define IRQ_SYSMMU_MDMA0_0 COMBINER_IRQ(4, 0)
-#define IRQ_SYSMMU_SSS_0 COMBINER_IRQ(4, 1)
-#define IRQ_SYSMMU_FIMC0_0 COMBINER_IRQ(4, 2)
-#define IRQ_SYSMMU_FIMC1_0 COMBINER_IRQ(4, 3)
-#define IRQ_SYSMMU_FIMC2_0 COMBINER_IRQ(4, 4)
-#define IRQ_SYSMMU_FIMC3_0 COMBINER_IRQ(4, 5)
-#define IRQ_SYSMMU_JPEG_0 COMBINER_IRQ(4, 6)
-#define IRQ_SYSMMU_2D_0 COMBINER_IRQ(4, 7)
-
-#define IRQ_SYSMMU_ROTATOR_0 COMBINER_IRQ(5, 0)
-#define IRQ_SYSMMU_MDMA1_0 COMBINER_IRQ(5, 1)
-#define IRQ_SYSMMU_LCD0_M0_0 COMBINER_IRQ(5, 2)
-#define IRQ_SYSMMU_LCD1_M1_0 COMBINER_IRQ(5, 3)
-#define IRQ_SYSMMU_TV_M0_0 COMBINER_IRQ(5, 4)
-#define IRQ_SYSMMU_MFC_M0_0 COMBINER_IRQ(5, 5)
-#define IRQ_SYSMMU_MFC_M1_0 COMBINER_IRQ(5, 6)
-#define IRQ_SYSMMU_PCIE_0 COMBINER_IRQ(5, 7)
+#define IRQ_SYSMMU_MDMA0 COMBINER_IRQ(4, 0)
+#define IRQ_SYSMMU_SSS COMBINER_IRQ(4, 1)
+#define IRQ_SYSMMU_FIMC0 COMBINER_IRQ(4, 2)
+#define IRQ_SYSMMU_FIMC1 COMBINER_IRQ(4, 3)
+#define IRQ_SYSMMU_FIMC2 COMBINER_IRQ(4, 4)
+#define IRQ_SYSMMU_FIMC3 COMBINER_IRQ(4, 5)
+#define IRQ_SYSMMU_JPEG COMBINER_IRQ(4, 6)
+#define IRQ_SYSMMU_2D COMBINER_IRQ(4, 7)
+
+#define IRQ_SYSMMU_ROTATOR COMBINER_IRQ(5, 0)
+#define IRQ_SYSMMU_MDMA1 COMBINER_IRQ(5, 1)
+#define IRQ_SYSMMU_FIMD0 COMBINER_IRQ(5, 2)
+#define IRQ_SYSMMU_FIMD1 COMBINER_IRQ(5, 3)
+#define IRQ_SYSMMU_TV COMBINER_IRQ(5, 4)
+#define IRQ_SYSMMU_MFC_L COMBINER_IRQ(5, 5)
+#define IRQ_SYSMMU_MFC_R COMBINER_IRQ(5, 6)
+#define IRQ_SYSMMU_PCIE COMBINER_IRQ(5, 7)
+
#define IRQ_PDMA0 COMBINER_IRQ(21, 0)
#define IRQ_PDMA1 COMBINER_IRQ(21, 1)
@@ -147,4 +148,5 @@
#define NR_IRQS (S5P_IRQ_EINT_BASE + 32)
+
#endif /* __ASM_ARCH_IRQS_H */
diff --git a/arch/arm/mach-s5pv310/include/mach/regs-clock.h b/arch/arm/mach-s5pv310/include/mach/regs-clock.h
index 341571a..9ef5f0c 100644
--- a/arch/arm/mach-s5pv310/include/mach/regs-clock.h
+++ b/arch/arm/mach-s5pv310/include/mach/regs-clock.h
@@ -67,6 +67,8 @@
#define S5P_CLKDIV_STAT_TOP S5P_CLKREG(0x0C610)
#define S5P_CLKGATE_IP_CAM S5P_CLKREG(0x0C920)
+#define S5P_CLKGATE_IP_MFC S5P_CLKREG(0x0C928)
+#define S5P_CLKGATE_IP_TV S5P_CLKREG(0x0C924)
#define S5P_CLKGATE_IP_IMAGE S5P_CLKREG(0x0C930)
#define S5P_CLKGATE_IP_LCD0 S5P_CLKREG(0x0C934)
#define S5P_CLKGATE_IP_LCD1 S5P_CLKREG(0x0C938)
@@ -78,6 +80,7 @@
#define S5P_CLKSRC_DMC S5P_CLKREG(0x10200)
#define S5P_CLKDIV_DMC0 S5P_CLKREG(0x10500)
#define S5P_CLKDIV_STAT_DMC0 S5P_CLKREG(0x10600)
+#define S5P_CLKGATE_IP_DMC S5P_CLKREG(0x10900)
#define S5P_APLL_LOCK S5P_CLKREG(0x14000)
#define S5P_MPLL_LOCK S5P_CLKREG(0x14004)
diff --git a/arch/arm/mach-s5pv310/include/mach/regs-sysmmu.h b/arch/arm/mach-s5pv310/include/mach/regs-sysmmu.h
index 0b28e81..dd2a954 100644
--- a/arch/arm/mach-s5pv310/include/mach/regs-sysmmu.h
+++ b/arch/arm/mach-s5pv310/include/mach/regs-sysmmu.h
@@ -13,12 +13,21 @@
#ifndef __ASM_ARCH_REGS_SYSMMU_H
#define __ASM_ARCH_REGS_SYSMMU_H __FILE__
-#define S5P_MMU_CTRL 0x000
-#define S5P_MMU_CFG 0x004
-#define S5P_MMU_STATUS 0x008
-#define S5P_MMU_FLUSH 0x00C
-#define S5P_PT_BASE_ADDR 0x014
-#define S5P_INT_STATUS 0x018
-#define S5P_PAGE_FAULT_ADDR 0x024
+#define S5P_MMU_CTRL (0x000)
+#define S5P_MMU_CFG (0x004)
+#define S5P_MMU_STATUS (0x008)
+#define S5P_MMU_FLUSH (0x00C)
+#define S5P_MMU_FLUSH_ENTRY (0x010)
+#define S5P_PT_BASE_ADDR (0x014)
+#define S5P_INT_STATUS (0x018)
+#define S5P_INT_CLEAR (0x01C)
+#define S5P_INT_MASK (0x020)
+#define S5P_PAGE_FAULT_ADDR (0x024)
+#define S5P_AW_FAULT_ADDR (0x028)
+#define S5P_AR_FAULT_ADDR (0x02C)
+#define S5P_DEFAULT_SLAVE_ADDR (0x030)
+#define S5P_MMU_VERSION (0x034)
+#define S5P_TLB_READ (0x038)
+#define S5P_TLB_DATA (0x03C)
#endif /* __ASM_ARCH_REGS_SYSMMU_H */
diff --git a/arch/arm/mach-s5pv310/include/mach/sysmmu.h b/arch/arm/mach-s5pv310/include/mach/sysmmu.h
deleted file mode 100644
index 598fc5c..0000000
--- a/arch/arm/mach-s5pv310/include/mach/sysmmu.h
+++ /dev/null
@@ -1,122 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/include/mach/sysmmu.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * Samsung sysmmu driver for S5PV310
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARM_ARCH_SYSMMU_H
-#define __ASM_ARM_ARCH_SYSMMU_H __FILE__
-
-#define S5PV310_SYSMMU_TOTAL_IPNUM 16
-#define S5P_SYSMMU_TOTAL_IPNUM S5PV310_SYSMMU_TOTAL_IPNUM
-
-enum s5pv310_sysmmu_ips {
- SYSMMU_MDMA,
- SYSMMU_SSS,
- SYSMMU_FIMC0,
- SYSMMU_FIMC1,
- SYSMMU_FIMC2,
- SYSMMU_FIMC3,
- SYSMMU_JPEG,
- SYSMMU_FIMD0,
- SYSMMU_FIMD1,
- SYSMMU_PCIe,
- SYSMMU_G2D,
- SYSMMU_ROTATOR,
- SYSMMU_MDMA2,
- SYSMMU_TV,
- SYSMMU_MFC_L,
- SYSMMU_MFC_R,
-};
-
-static char *sysmmu_ips_name[S5PV310_SYSMMU_TOTAL_IPNUM] = {
- "SYSMMU_MDMA" ,
- "SYSMMU_SSS" ,
- "SYSMMU_FIMC0" ,
- "SYSMMU_FIMC1" ,
- "SYSMMU_FIMC2" ,
- "SYSMMU_FIMC3" ,
- "SYSMMU_JPEG" ,
- "SYSMMU_FIMD0" ,
- "SYSMMU_FIMD1" ,
- "SYSMMU_PCIe" ,
- "SYSMMU_G2D" ,
- "SYSMMU_ROTATOR",
- "SYSMMU_MDMA2" ,
- "SYSMMU_TV" ,
- "SYSMMU_MFC_L" ,
- "SYSMMU_MFC_R" ,
-};
-
-typedef enum s5pv310_sysmmu_ips sysmmu_ips;
-
-struct sysmmu_tt_info {
- unsigned long *pgd;
- unsigned long pgd_paddr;
- unsigned long *pte;
-};
-
-struct sysmmu_controller {
- const char *name;
-
- /* channels registers */
- void __iomem *regs;
-
- /* channel irq */
- unsigned int irq;
-
- sysmmu_ips ips;
-
- /* Translation Table Info. */
- struct sysmmu_tt_info *tt_info;
-
- struct resource *mem;
- struct device *dev;
-
- /* SysMMU controller enable - true : enable */
- bool enable;
-};
-
-/**
- * s5p_sysmmu_enable() - enable system mmu of ip
- * @ips: The ip connected system mmu.
- *
- * This function enable system mmu to transfer address
- * from virtual address to physical address
- */
-int s5p_sysmmu_enable(sysmmu_ips ips);
-
-/**
- * s5p_sysmmu_disable() - disable sysmmu mmu of ip
- * @ips: The ip connected system mmu.
- *
- * This function disable system mmu to transfer address
- * from virtual address to physical address
- */
-int s5p_sysmmu_disable(sysmmu_ips ips);
-
-/**
- * s5p_sysmmu_set_tablebase_pgd() - set page table base address to refer page table
- * @ips: The ip connected system mmu.
- * @pgd: The page table base address.
- *
- * This function set page table base address
- * When system mmu transfer address from virtaul address to physical address,
- * system mmu refer address information from page table
- */
-int s5p_sysmmu_set_tablebase_pgd(sysmmu_ips ips, unsigned long pgd);
-
-/**
- * s5p_sysmmu_tlb_invalidate() - flush all TLB entry in system mmu
- * @ips: The ip connected system mmu.
- *
- * This function flush all TLB entry in system mmu
- */
-int s5p_sysmmu_tlb_invalidate(sysmmu_ips ips);
-#endif /* __ASM_ARM_ARCH_SYSMMU_H */
diff --git a/arch/arm/plat-s5p/Kconfig b/arch/arm/plat-s5p/Kconfig
index 0db2a7a..4166964 100644
--- a/arch/arm/plat-s5p/Kconfig
+++ b/arch/arm/plat-s5p/Kconfig
@@ -37,14 +37,6 @@ config S5P_GPIO_INT
help
Common code for the GPIO interrupts (other than external interrupts.)
-comment "System MMU"
-
-config S5P_SYSTEM_MMU
- bool "S5P SYSTEM MMU"
- depends on ARCH_S5PV310
- help
- Say Y here if you want to enable System MMU
-
config S5P_DEV_FIMC0
bool
help
@@ -79,3 +71,12 @@ config S5P_DEV_CSIS1
bool
help
Compile in platform device definitions for MIPI-CSIS channel 1
+
+comment "System MMU"
+
+config S5P_SYSTEM_MMU
+ bool "S5P SYSTEM MMU"
+ depends on ARCH_S5PV310
+ help
+ Say Y here if you want to enable System MMU
+
diff --git a/arch/arm/plat-s5p/include/plat/sysmmu.h b/arch/arm/plat-s5p/include/plat/sysmmu.h
new file mode 100644
index 0000000..9051af4
--- /dev/null
+++ b/arch/arm/plat-s5p/include/plat/sysmmu.h
@@ -0,0 +1,127 @@
+/*
+ * sysmmu.h
+ *
+ * Copyright (C) 2011 Samsung Electronics
+ *
+ * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ */
+#ifndef __S5P_SYSMMU_H__
+#define __S5P_SYSMMU_H__
+
+struct device;
+
+/**
+ * enum s5p_sysmmu_cmd - sysmmu control commands
+ * @S5P_SYSMMU_ENABLE_SHARED: enable sysmmu, share page tables with ARM CPU
+ * @S5P_SYSMMU_ENABLE_PRIVATE: enable sysmmu, use private page tables
+ * @S5P_SYSMMU_DISABLE: disable sysmmu
+ * @S5P_SYSMMU_TLB_INVALIDATE: invalidate sysmmu TLB contents
+ */
+enum s5p_sysmmu_cmd {
+ S5P_SYSMMU_ENABLE_SHARED,
+ S5P_SYSMMU_ENABLE_PRIVATE,
+ S5P_SYSMMU_DISABLE,
+ S5P_SYSMMU_TLB_INVALIDATE,
+};
+
+/**
+ * enum s5p_sysmmu_ip - integrated peripherals identifiers
+ * @S5P_SYSMMU_MDMA: MDMA
+ * @S5P_SYSMMU_SSS: SSS
+ * @S5P_SYSMMU_FIMC0: FIMC0
+ * @S5P_SYSMMU_FIMC1: FIMC1
+ * @S5P_SYSMMU_FIMC2: FIMC2
+ * @S5P_SYSMMU_FIMC3: FIMC3
+ * @S5P_SYSMMU_JPEG: JPEG
+ * @S5P_SYSMMU_FIMD0: FIMD0
+ * @S5P_SYSMMU_FIMD1: FIMD1
+ * @S5P_SYSMMU_PCIe: PCIe
+ * @S5P_SYSMMU_G2D: G2D
+ * @S5P_SYSMMU_ROTATOR: ROTATOR
+ * @S5P_SYSMMU_MDMA2: MDMA2
+ * @S5P_SYSMMU_TV: TV
+ * @S5P_SYSMMU_MFC_L: MFC_L
+ * @S5P_SYSMMU_MFC_R: MFC_R
+ */
+enum s5p_sysmmu_ip {
+ S5P_SYSMMU_MDMA,
+ S5P_SYSMMU_SSS,
+ S5P_SYSMMU_FIMC0,
+ S5P_SYSMMU_FIMC1,
+ S5P_SYSMMU_FIMC2,
+ S5P_SYSMMU_FIMC3,
+ S5P_SYSMMU_JPEG,
+ S5P_SYSMMU_FIMD0,
+ S5P_SYSMMU_FIMD1,
+ S5P_SYSMMU_PCIe,
+ S5P_SYSMMU_G2D,
+ S5P_SYSMMU_ROTATOR,
+ S5P_SYSMMU_MDMA2,
+ S5P_SYSMMU_TV,
+ S5P_SYSMMU_MFC_L,
+ S5P_SYSMMU_MFC_R,
+};
+
+/**
+ * s5p_sysmmu_get() - get sysmmu handle for a device
+ * @dev: device which needs to use its sysmmu
+ * @ip: integrated peripheral identifier of the device
+ */
+void *s5p_sysmmu_get(struct device *dev, enum s5p_sysmmu_ip ip);
+
+/**
+ * s5p_sysmmu_put() - release sysmmu handle for a device
+ * @dev_id: sysmmu handle obtained from s5p_sysmmu_get()
+ */
+void s5p_sysmmu_put(void *dev_id);
+
+/**
+ * s5p_sysmmu_control() - control a sysmmu
+ * @dev_id: sysmmu handle obtained from s5p_sysmmu_get()
+ * @cmd: command to perform
+ */
+int s5p_sysmmu_control(void *dev_id, enum s5p_sysmmu_cmd cmd);
+
+/**
+ * s5p_sysmmu_map_area() - map an area of device's virtual memory,
+ underlying memory is described by struct pages
+ * @dev_id: sysmmu handle obtained from s5p_sysmmu_get()
+ * @varea_start: beginning virtual address of the mapped area,
+ * must be page aligned
+ * @num_pages: number of pages to map starting from varea_start
+ * @pages: an array of struct page pointers representing
+ * the physical pages which will be mapped
+ */
+int s5p_sysmmu_map_area(void *dev_id, unsigned long varea_start,
+ unsigned long num_pages, struct page **pages);
+
+/**
+ * s5p_sysmmu_map_phys_area() - map an area of device's virtual memory,
+ * underlying memory is a physically contiguous block
+ * @dev_id: sysmmu handle obtained from s5p_sysmmu_get()
+ * @varea_start: beginning virtual address of the mapped area,
+ * must be page aligned
+ * @phys_area_start: beginning physical adddress of the underlying memory
+ * @num_pages: number of pages to map starting from phys_area_start
+ */
+int s5p_sysmmu_map_phys_area(void *dev_id, unsigned long varea_start,
+ unsigned long phys_area_start,
+ unsigned long num_pages);
+
+/**
+ * s5p_sysmmu_unmap_area() - unmap an area of device's virtual memory
+ * @dev_id: sysmmu handle obtained from s5p_sysmmu_get()
+ * @varea_start: beginning virtual address of the mapped area,
+ * must be page aligned and correspond to the address
+ * used while mapping
+ * @num_pages: number of pages to unmap starting from phys_area_start,
+ * must correspond to the number used while mapping
+ */
+void s5p_sysmmu_unmap_area(void *dev_id, unsigned long varea_start,
+ unsigned long num_pages);
+
+#endif /* __S5P_SYSMMU_H__ */
diff --git a/arch/arm/plat-s5p/sysmmu.c b/arch/arm/plat-s5p/sysmmu.c
dissimilarity index 85%
index ffe8a48..45adbf4 100644
--- a/arch/arm/plat-s5p/sysmmu.c
+++ b/arch/arm/plat-s5p/sysmmu.c
@@ -1,326 +1,662 @@
-/* linux/arch/arm/plat-s5p/sysmmu.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/io.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-
-#include <mach/map.h>
-#include <mach/regs-sysmmu.h>
-#include <mach/sysmmu.h>
-
-struct sysmmu_controller s5p_sysmmu_cntlrs[S5P_SYSMMU_TOTAL_IPNUM];
-
-void s5p_sysmmu_register(struct sysmmu_controller *sysmmuconp)
-{
- unsigned int reg_mmu_ctrl;
- unsigned int reg_mmu_status;
- unsigned int reg_pt_base_addr;
- unsigned int reg_int_status;
- unsigned int reg_page_ft_addr;
-
- reg_int_status = __raw_readl(sysmmuconp->regs + S5P_INT_STATUS);
- reg_mmu_ctrl = __raw_readl(sysmmuconp->regs + S5P_MMU_CTRL);
- reg_mmu_status = __raw_readl(sysmmuconp->regs + S5P_MMU_STATUS);
- reg_pt_base_addr = __raw_readl(sysmmuconp->regs + S5P_PT_BASE_ADDR);
- reg_page_ft_addr = __raw_readl(sysmmuconp->regs + S5P_PAGE_FAULT_ADDR);
-
- printk(KERN_INFO "%s: ips:%s\n", __func__, sysmmuconp->name);
- printk(KERN_INFO "%s: MMU_CTRL:0x%X, ", __func__, reg_mmu_ctrl);
- printk(KERN_INFO "MMU_STATUS:0x%X, PT_BASE_ADDR:0x%X\n", reg_mmu_status, reg_pt_base_addr);
- printk(KERN_INFO "%s: INT_STATUS:0x%X, PAGE_FAULT_ADDR:0x%X\n", __func__, reg_int_status, reg_page_ft_addr);
-
- switch (reg_int_status & 0xFF) {
- case 0x1:
- printk(KERN_INFO "%s: Page fault\n", __func__);
- printk(KERN_INFO "%s: Virtual address causing last page fault or bus error : 0x%x\n", __func__ , reg_page_ft_addr);
- break;
- case 0x2:
- printk(KERN_INFO "%s: AR multi-hit fault\n", __func__);
- break;
- case 0x4:
- printk(KERN_INFO "%s: AW multi-hit fault\n", __func__);
- break;
- case 0x8:
- printk(KERN_INFO "%s: Bus error\n", __func__);
- break;
- case 0x10:
- printk(KERN_INFO "%s: AR Security protection fault\n", __func__);
- break;
- case 0x20:
- printk(KERN_INFO "%s: AR Access protection fault\n", __func__);
- break;
- case 0x40:
- printk(KERN_INFO "%s: AW Security protection fault\n", __func__);
- break;
- case 0x80:
- printk(KERN_INFO "%s: AW Access protection fault\n", __func__);
- break;
- }
-}
-
-static irqreturn_t s5p_sysmmu_irq(int irq, void *dev_id)
-{
- unsigned int i;
- unsigned int reg_int_status;
- struct sysmmu_controller *sysmmuconp;
-
- for (i = 0; i < S5P_SYSMMU_TOTAL_IPNUM; i++) {
- sysmmuconp = &s5p_sysmmu_cntlrs[i];
-
- if (sysmmuconp->enable == true) {
- reg_int_status = __raw_readl(sysmmuconp->regs + S5P_INT_STATUS);
-
- if (reg_int_status & 0xFF)
- s5p_sysmmu_register(sysmmuconp);
- }
- }
- return IRQ_HANDLED;
-}
-
-int s5p_sysmmu_set_tablebase_pgd(sysmmu_ips ips, unsigned long pgd)
-{
- struct sysmmu_controller *sysmmuconp = NULL;
-
- sysmmuconp = &s5p_sysmmu_cntlrs[ips];
-
- if (sysmmuconp == NULL) {
- printk(KERN_ERR "failed to get ip's sysmmu info\n");
- return 1;
- }
-
- /* Set sysmmu page table base address */
- __raw_writel(pgd, sysmmuconp->regs + S5P_PT_BASE_ADDR);
-
- if (s5p_sysmmu_tlb_invalidate(ips) != 0)
- printk(KERN_ERR "failed s5p_sysmmu_tlb_invalidate\n");
-
- return 0;
-}
-
-static int s5p_sysmmu_set_tablebase(sysmmu_ips ips)
-{
- unsigned int pg;
- struct sysmmu_controller *sysmmuconp;
-
- sysmmuconp = &s5p_sysmmu_cntlrs[ips];
-
- if (sysmmuconp == NULL) {
- printk(KERN_ERR "failed to get ip's sysmmu info\n");
- return 1;
- }
-
- __asm__("mrc p15, 0, %0, c2, c0, 0" \
- : "=r" (pg) : : "cc"); \
- pg &= ~0x3fff;
-
- printk(KERN_INFO "%s: CP15 TTBR0 : 0x%x\n", __func__, pg);
-
- /* Set sysmmu page table base address */
- __raw_writel(pg, sysmmuconp->regs + S5P_PT_BASE_ADDR);
-
- return 0;
-}
-
-int s5p_sysmmu_enable(sysmmu_ips ips)
-{
- unsigned int reg;
-
- struct sysmmu_controller *sysmmuconp;
-
- sysmmuconp = &s5p_sysmmu_cntlrs[ips];
-
- if (sysmmuconp == NULL) {
- printk(KERN_ERR "failed to get ip's sysmmu info\n");
- return 1;
- }
-
- s5p_sysmmu_set_tablebase(ips);
-
- /* replacement policy : LRU */
- reg = __raw_readl(sysmmuconp->regs + S5P_MMU_CFG);
- reg |= 0x1;
- __raw_writel(reg, sysmmuconp->regs + S5P_MMU_CFG);
-
- /* Enable interrupt, Enable MMU */
- reg = __raw_readl(sysmmuconp->regs + S5P_MMU_CTRL);
- reg |= (0x1 << 2) | (0x1 << 0);
-
- __raw_writel(reg, sysmmuconp->regs + S5P_MMU_CTRL);
-
- sysmmuconp->enable = true;
-
- return 0;
-}
-
-int s5p_sysmmu_disable(sysmmu_ips ips)
-{
- unsigned int reg;
-
- struct sysmmu_controller *sysmmuconp = NULL;
-
- if (ips > S5P_SYSMMU_TOTAL_IPNUM)
- printk(KERN_ERR "failed to get ips parameter\n");
-
- sysmmuconp = &s5p_sysmmu_cntlrs[ips];
-
- if (sysmmuconp == NULL) {
- printk(KERN_ERR "failed to get ip's sysmmu info\n");
- return 1;
- }
-
- reg = __raw_readl(sysmmuconp->regs + S5P_MMU_CFG);
-
- /* replacement policy : LRU */
- reg |= 0x1;
- __raw_writel(reg, sysmmuconp->regs + S5P_MMU_CFG);
-
- reg = __raw_readl(sysmmuconp->regs + S5P_MMU_CTRL);
-
- /* Disable MMU */
- reg &= ~0x1;
- __raw_writel(reg, sysmmuconp->regs + S5P_MMU_CTRL);
-
- sysmmuconp->enable = false;
-
- return 0;
-}
-
-int s5p_sysmmu_tlb_invalidate(sysmmu_ips ips)
-{
- unsigned int reg;
- struct sysmmu_controller *sysmmuconp = NULL;
-
- sysmmuconp = &s5p_sysmmu_cntlrs[ips];
-
- if (sysmmuconp == NULL) {
- printk(KERN_ERR "failed to get ip's sysmmu info\n");
- return 1;
- }
-
- /* set Block MMU for flush TLB */
- reg = __raw_readl(sysmmuconp->regs + S5P_MMU_CTRL);
- reg |= 0x1 << 1;
- __raw_writel(reg, sysmmuconp->regs + S5P_MMU_CTRL);
-
- /* flush all TLB entry */
- __raw_writel(0x1, sysmmuconp->regs + S5P_MMU_FLUSH);
-
- /* set Un-block MMU after flush TLB */
- reg = __raw_readl(sysmmuconp->regs + S5P_MMU_CTRL);
- reg &= ~(0x1 << 1);
- __raw_writel(reg, sysmmuconp->regs + S5P_MMU_CTRL);
-
- return 0;
-}
-
-static int s5p_sysmmu_probe(struct platform_device *pdev)
-{
- int i;
- int ret;
- struct resource *res;
- struct sysmmu_controller *sysmmuconp;
- sysmmu_ips ips;
-
- for (i = 0; i < S5P_SYSMMU_TOTAL_IPNUM; i++) {
- sysmmuconp = &s5p_sysmmu_cntlrs[i];
- if (sysmmuconp == NULL) {
- printk(KERN_ERR "failed to get ip's sysmmu info\n");
- ret = -ENOENT;
- goto err_res;
- }
-
- sysmmuconp->name = sysmmu_ips_name[i];
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, i);
- if (!res) {
- printk(KERN_ERR "failed to get sysmmu resource\n");
- ret = -ENODEV;
- goto err_res;
- }
-
- sysmmuconp->mem = request_mem_region(res->start,
- ((res->end) - (res->start)) + 1, pdev->name);
- if (!sysmmuconp->mem) {
- pr_err("failed to request sysmmu memory region\n");
- ret = -EBUSY;
- goto err_res;
- }
-
- sysmmuconp->regs = ioremap(res->start, res->end - res->start + 1);
- if (!sysmmuconp->regs) {
- pr_err("failed to sysmmu ioremap\n");
- ret = -ENXIO;
- goto err_reg;
- }
-
- sysmmuconp->irq = platform_get_irq(pdev, i);
- if (sysmmuconp->irq <= 0) {
- pr_err("failed to get sysmmu irq resource\n");
- ret = -ENOENT;
- goto err_map;
- }
-
- ret = request_irq(sysmmuconp->irq, s5p_sysmmu_irq, IRQF_DISABLED, pdev->name, sysmmuconp);
- if (ret) {
- pr_err("failed to request irq\n");
- ret = -ENOENT;
- goto err_map;
- }
-
- ips = (sysmmu_ips)i;
-
- sysmmuconp->ips = ips;
- }
-
- return 0;
-
-err_reg:
- release_mem_region((resource_size_t)sysmmuconp->mem, (resource_size_t)((res->end) - (res->start) + 1));
-err_map:
- iounmap(sysmmuconp->regs);
-err_res:
- return ret;
-}
-
-static int s5p_sysmmu_remove(struct platform_device *pdev)
-{
- return 0;
-}
-int s5p_sysmmu_runtime_suspend(struct device *dev)
-{
- return 0;
-}
-
-int s5p_sysmmu_runtime_resume(struct device *dev)
-{
- return 0;
-}
-
-const struct dev_pm_ops s5p_sysmmu_pm_ops = {
- .runtime_suspend = s5p_sysmmu_runtime_suspend,
- .runtime_resume = s5p_sysmmu_runtime_resume,
-};
-
-static struct platform_driver s5p_sysmmu_driver = {
- .probe = s5p_sysmmu_probe,
- .remove = s5p_sysmmu_remove,
- .driver = {
- .owner = THIS_MODULE,
- .name = "s5p-sysmmu",
- .pm = &s5p_sysmmu_pm_ops,
- }
-};
-
-static int __init s5p_sysmmu_init(void)
-{
- return platform_driver_register(&s5p_sysmmu_driver);
-}
-arch_initcall(s5p_sysmmu_init);
+/* linux/arch/arm/plat-s5p/sysmmu.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/gfp.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+#include <linux/dma-mapping.h>
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/pm_runtime.h>
+
+#include <asm/memory.h>
+
+#include <plat/irqs.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
+#include <plat/sysmmu.h>
+
+#include <mach/map.h>
+#include <mach/regs-sysmmu.h>
+
+static int debug;
+module_param(debug, int, 0644);
+
+#define sysmmu_debug(level, fmt, arg...) \
+ do { \
+ if (debug >= level) \
+ printk(KERN_DEBUG "[%s] " fmt, __func__, ## arg);\
+ } while (0)
+
+struct s5p_sysmmu_info {
+ struct mutex mutex;
+ struct resource *ioarea;
+ void __iomem *regs;
+ unsigned int irq;
+ struct clk *clk;
+ bool enabled;
+ bool page_tables_allocated;
+ enum s5p_sysmmu_ip ip;
+ enum s5p_sysmmu_cmd mode;
+
+ unsigned long flpt;
+ unsigned long flpt_vaddr;
+ /* one table entry per 4 entries of the first level page table */
+ unsigned long *vaddr;
+ /* one table entry per 4 entries of the first level page table */
+ u16 *refcount;
+
+ struct device *dev;
+
+ struct list_head entry;
+};
+
+static LIST_HEAD(sysmmu_list);
+static DEFINE_SPINLOCK(sysmmu_list_slock);
+
+void *s5p_sysmmu_get(struct device *dev, enum s5p_sysmmu_ip ip)
+{
+ struct s5p_sysmmu_info *ret;
+ unsigned long flags;
+
+ sysmmu_debug(3, "for %s\n", dev_name(dev));
+
+ spin_lock_irqsave(&sysmmu_list_slock, flags);
+ list_for_each_entry(ret, &sysmmu_list, entry) {
+ if (ret->ip == ip) {
+ try_module_get(THIS_MODULE);
+ spin_unlock_irqrestore(&sysmmu_list_slock, flags);
+ return ret;
+ }
+ }
+ spin_unlock_irqrestore(&sysmmu_list_slock, flags);
+
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(s5p_sysmmu_get);
+
+void s5p_sysmmu_put(void *dev_id)
+{
+ module_put(THIS_MODULE);
+}
+EXPORT_SYMBOL_GPL(s5p_sysmmu_put);
+
+static void s5p_sysmmu_configure(struct s5p_sysmmu_info *sysmmu,
+ unsigned long pg)
+{
+ unsigned int reg;
+
+ writel(pg, sysmmu->regs + S5P_PT_BASE_ADDR);
+
+ reg = readl(sysmmu->regs + S5P_MMU_CFG);
+ reg |= (0x1<<0); /* replacement policy : LRU */
+ writel(reg, sysmmu->regs + S5P_MMU_CFG);
+
+ reg = readl(sysmmu->regs + S5P_MMU_CTRL);
+ reg |= ((0x1<<2)|(0x1<<0)); /* Enable interrupt, Enable MMU */
+ writel(reg, sysmmu->regs + S5P_MMU_CTRL);
+
+ sysmmu_debug(3, "CFG:0x%x\n", readl(sysmmu->regs + S5P_MMU_CFG));
+ sysmmu_debug(3, "CTRL:0x%x\n", readl(sysmmu->regs + S5P_MMU_CTRL));
+ sysmmu_debug(3, "STATUS:0x%x\n", readl(sysmmu->regs + S5P_MMU_STATUS));
+
+ sysmmu->enabled = true;
+}
+
+static int s5p_sysmmu_control_locked(struct s5p_sysmmu_info *sysmmu,
+ enum s5p_sysmmu_cmd cmd)
+{
+ unsigned int pg, reg;
+
+ sysmmu_debug(3, "%d\n", cmd);
+
+ sysmmu->mode = cmd;
+
+ switch (cmd) {
+ case S5P_SYSMMU_ENABLE_SHARED:
+ /*
+ * coprocessor 15 == mmu;
+ * copy system page tables base from there
+ */
+ __asm__("mrc p15, 0, %0, c2, c0, 0" : "=r" (pg) : : "cc");
+ pg &= ~0x3fff;
+
+ s5p_sysmmu_configure(sysmmu, pg);
+
+ return 0;
+ break;
+
+ case S5P_SYSMMU_ENABLE_PRIVATE:
+ pm_runtime_get_sync(sysmmu->dev);
+ if (!sysmmu->page_tables_allocated) {
+ /*
+ * first-level page table holds
+ * 4k second-level descriptors == 16kB == 4 pages
+ */
+ sysmmu->flpt_vaddr = (unsigned long)dma_alloc_coherent(
+ sysmmu->dev,
+ 4 * PAGE_SIZE,
+ (dma_addr_t *)&sysmmu->flpt,
+ GFP_KERNEL | __GFP_ZERO);
+ if (!sysmmu->flpt_vaddr)
+ return -ENOMEM;
+
+ sysmmu->refcount = kzalloc(1024 * sizeof(u16),
+ GFP_KERNEL);
+ if (!sysmmu->refcount) {
+ dma_free_coherent(sysmmu->dev, 4 * PAGE_SIZE,
+ (dma_addr_t *)sysmmu->flpt_vaddr,
+ sysmmu->flpt);
+ return -ENOMEM;
+ }
+
+ sysmmu->vaddr = kzalloc(1024 * sizeof(unsigned long),
+ GFP_KERNEL);
+ if (!sysmmu->vaddr) {
+ kfree(sysmmu->refcount);
+ dma_free_coherent(sysmmu->dev, 4 * PAGE_SIZE,
+ (void *)sysmmu->flpt_vaddr,
+ sysmmu->flpt);
+ return -ENOMEM;
+ }
+ sysmmu->page_tables_allocated = true;
+ }
+ s5p_sysmmu_configure(sysmmu, sysmmu->flpt);
+
+ return 0;
+ break;
+
+ case S5P_SYSMMU_DISABLE:
+ reg = readl(sysmmu->regs + S5P_MMU_CFG);
+ reg |= (0x1<<0); /* replacement policy : LRU */
+ writel(reg, sysmmu->regs + S5P_MMU_CFG);
+
+ reg = readl(sysmmu->regs + S5P_MMU_CTRL);
+ reg &= ~(0x1); /* Disable MMU */
+ writel(reg, sysmmu->regs + S5P_MMU_CTRL);
+ sysmmu->enabled = false;
+ pm_runtime_put_sync(sysmmu->dev);
+ return 0;
+ break;
+
+ case S5P_SYSMMU_TLB_INVALIDATE:
+ reg = readl(sysmmu->regs + S5P_MMU_CTRL);
+ reg |= (0x1<<1); /* Block MMU */
+ writel(reg, sysmmu->regs + S5P_MMU_CTRL);
+
+ writel(0x1, sysmmu->regs + S5P_MMU_FLUSH);
+ /* Flush_entry */
+
+ reg = readl(sysmmu->regs + S5P_MMU_CTRL);
+ reg &= ~(0x1<<1); /* Un-block MMU */
+ writel(reg, sysmmu->regs + S5P_MMU_CTRL);
+ return 0;
+ break;
+
+ default:
+ ;
+ }
+ return -EINVAL;
+}
+
+int s5p_sysmmu_control(void *dev_id, enum s5p_sysmmu_cmd cmd)
+{
+ struct s5p_sysmmu_info *sysmmu = dev_id;
+ int ret;
+
+ mutex_lock(&sysmmu->mutex);
+ ret = s5p_sysmmu_control_locked(sysmmu, cmd);
+ mutex_unlock(&sysmmu->mutex);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(s5p_sysmmu_control);
+
+#define dereference_vaddr(vaddr) (*((unsigned long *)(vaddr)))
+
+#define make_flpt_entry(slpt, k) \
+ ((((slpt) + (k) * 256 * 4) & ~0x3FF) | 0x1)
+#define make_slpt_phys_entry(phys) (((phys) & ~0xFFF) | 0x2)
+
+#define flpt_offset(vaddr) (((vaddr) >> 18) & 0x3FFC)
+#define slpt_offset(slpt, vaddr) \
+ (((slpt) & (0x3 << 10)) + (((vaddr) >> 10) & 0x3FC))
+
+#define slpt_number(vaddr) (((vaddr) >> 22) & 0x3FF)
+
+#define get_slpt(flpt_entry_vaddr) \
+ (dereference_vaddr(flpt_entry_vaddr) & ~0x3FF)
+#define get_slpt_four(flpt_entry_vaddr) \
+ (dereference_vaddr(flpt_entry_vaddr) & ~0xFFF)
+
+#define invalidate_slpt_entry(slpt_entry_vaddr) \
+ (dereference_vaddr(slpt_entry_vaddr) &= ~0x3)
+
+/*
+ * vaddr:
+ * X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X 0 0
+ * 31--------------------20 19------------12 11--------------------0
+ * index into flpt idx into slpt offset within page
+ */
+static int s5p_sysmmu_map_page(struct s5p_sysmmu_info *sysmmu,
+ unsigned long vaddr, unsigned long paddr)
+{
+ unsigned long flpt_entry_vaddr, slpt_entry_vaddr, slpt, slpt_vaddr;
+ int four_entry = slpt_number(vaddr);
+
+ flpt_entry_vaddr = sysmmu->flpt_vaddr + flpt_offset(vaddr);
+ if (0 == dereference_vaddr(flpt_entry_vaddr)) {
+ int k;
+ unsigned long flpt_four = flpt_entry_vaddr & ~0xF;
+
+ slpt_vaddr = (unsigned long)dma_alloc_coherent(
+ sysmmu->dev,
+ PAGE_SIZE,
+ (dma_addr_t *)&slpt,
+ GFP_KERNEL | __GFP_ZERO);
+ if (!slpt_vaddr)
+ return -1;
+
+ sysmmu->vaddr[four_entry] = slpt_vaddr;
+
+ for (k = 0; k < 4; ++k)
+ dereference_vaddr(flpt_four + 4 * k) =
+ make_flpt_entry(slpt, k);
+
+ sysmmu_debug(3, "4-entry:%d\n", four_entry);
+ }
+ slpt = get_slpt(flpt_entry_vaddr);
+ slpt_entry_vaddr = sysmmu->vaddr[four_entry] + slpt_offset(slpt, vaddr);
+ dereference_vaddr(slpt_entry_vaddr) = make_slpt_phys_entry(paddr);
+ sysmmu->refcount[four_entry]++;
+
+ return 0;
+}
+
+static void s5p_unmap_page(struct s5p_sysmmu_info *sysmmu, unsigned long vaddr)
+{
+ unsigned long flpt_entry_vaddr, slpt_entry_vaddr, slpt;
+ int four_entry = slpt_number(vaddr);
+
+ flpt_entry_vaddr = sysmmu->flpt_vaddr + flpt_offset(vaddr);
+ if (--sysmmu->refcount[four_entry]) {
+ slpt = get_slpt(flpt_entry_vaddr);
+ slpt_entry_vaddr = sysmmu->vaddr[four_entry] +
+ slpt_offset(slpt, vaddr);
+ invalidate_slpt_entry(slpt_entry_vaddr);
+ } else {
+ dma_free_coherent(sysmmu->dev, PAGE_SIZE,
+ (void *)sysmmu->vaddr[four_entry],
+ get_slpt_four(flpt_entry_vaddr));
+
+ memset((void *)(flpt_entry_vaddr & ~0xF), 0, 16);
+
+ sysmmu->vaddr[four_entry] = 0;
+ }
+}
+
+int s5p_sysmmu_map_area(void *dev_id, unsigned long varea_start,
+ unsigned long num_pages, struct page **pages)
+{
+ struct s5p_sysmmu_info *sysmmu = dev_id;
+ int i, ret;
+
+ sysmmu_debug(3, "varea_start:0x%lx, num_pages:%ld\n",
+ varea_start, num_pages);
+
+ mutex_lock(&sysmmu->mutex);
+ for (i = 0; i < num_pages; varea_start += PAGE_SIZE, ++i) {
+ ret = s5p_sysmmu_map_page(sysmmu,
+ varea_start, page_to_phys(pages[i]));
+ if (ret < 0)
+ goto slpt_pg_alloc_fail;
+ }
+
+ mutex_unlock(&sysmmu->mutex);
+
+ sysmmu_debug(3, "MAPPING DONE for varea_start:0x%lx, num_pages:%ld\n",
+ varea_start - num_pages * PAGE_SIZE, num_pages);
+
+ return 0;
+
+slpt_pg_alloc_fail:
+ while (--i >= 0) {
+ varea_start -= PAGE_SIZE;
+ s5p_unmap_page(sysmmu, varea_start);
+ }
+ s5p_sysmmu_control_locked(sysmmu, S5P_SYSMMU_TLB_INVALIDATE);
+ mutex_unlock(&sysmmu->mutex);
+ return -1;
+}
+EXPORT_SYMBOL_GPL(s5p_sysmmu_map_area);
+
+int s5p_sysmmu_map_phys_area(void *dev_id, unsigned long varea_start,
+ unsigned long phys_area_start, unsigned long num_pages)
+{
+ struct s5p_sysmmu_info *sysmmu = dev_id;
+ int i;
+
+ sysmmu_debug(3, "varea_start:0x%lx, num_pages:%ld\n",
+ varea_start, num_pages);
+
+ mutex_lock(&sysmmu->mutex);
+ for (i = 0; i < num_pages;
+ varea_start += PAGE_SIZE, phys_area_start += PAGE_SIZE, ++i)
+ if (s5p_sysmmu_map_page(sysmmu, varea_start, phys_area_start) < 0)
+ goto slpt_pg_alloc_fail;
+
+ mutex_unlock(&sysmmu->mutex);
+
+ sysmmu_debug(3, "MAPPING DONE for varea_start:0x%lx, num_pages:%ld\n",
+ varea_start - num_pages * PAGE_SIZE, num_pages);
+
+ return 0;
+
+slpt_pg_alloc_fail:
+ while (--i >= 0) {
+ varea_start -= PAGE_SIZE;
+ s5p_unmap_page(sysmmu, varea_start);
+ }
+ s5p_sysmmu_control_locked(sysmmu, S5P_SYSMMU_TLB_INVALIDATE);
+ mutex_unlock(&sysmmu->mutex);
+ return -1;
+}
+EXPORT_SYMBOL_GPL(s5p_sysmmu_map_phys_area);
+
+void s5p_sysmmu_unmap_area(void *dev_id, unsigned long varea_start,
+ unsigned long num_pages)
+{
+ struct s5p_sysmmu_info *sysmmu = dev_id;
+ unsigned long vaddr = varea_start;
+ int i;
+
+ mutex_lock(&sysmmu->mutex);
+
+ sysmmu_debug(3, "varea_start:0x%lx, num_pages:%ld\n",
+ varea_start, num_pages);
+
+ for (i = 0; i < num_pages; vaddr += PAGE_SIZE, ++i)
+ s5p_unmap_page(sysmmu, vaddr);
+
+ s5p_sysmmu_control_locked(sysmmu, S5P_SYSMMU_TLB_INVALIDATE);
+ mutex_unlock(&sysmmu->mutex);
+
+ sysmmu_debug(3, "UNMAPPING DONE for varea_start:0x%lx, num_pages:%ld\n",
+ varea_start, num_pages);
+
+ return;
+}
+EXPORT_SYMBOL_GPL(s5p_sysmmu_unmap_area)
+
+static void s5p_sysmmu_pg_fault(struct s5p_sysmmu_info *sysmmu)
+{
+ void __iomem *regbase = sysmmu->regs;
+ unsigned long fault;
+
+ fault = readl(regbase + S5P_PAGE_FAULT_ADDR);
+ sysmmu_debug(3, "Page fault occured for virtual address 0x%08lx\n",
+ fault);
+}
+
+static irqreturn_t s5p_sysmmu_irq(int irq, void *dev_id)
+{
+ struct s5p_sysmmu_info *sysmmu = dev_id;
+ unsigned int reg_INT_STATUS;
+
+ if (false == sysmmu->enabled)
+ return IRQ_HANDLED;
+
+ reg_INT_STATUS = readl(sysmmu->regs + S5P_INT_STATUS);
+ if (reg_INT_STATUS & 0xFF) {
+ switch (reg_INT_STATUS & 0xFF) {
+ case 0x1:
+ /* page fault */
+ sysmmu_debug(3, "irq:pg fault\n");
+ s5p_sysmmu_pg_fault(sysmmu);
+ break;
+ case 0x2:
+ /* AR multi-hit fault */
+ sysmmu_debug(3, "irq:ar multi hit\n");
+ break;
+ case 0x4:
+ /* AW multi-hit fault */
+ sysmmu_debug(3, "irq:aw multi hit\n");
+ break;
+ case 0x8:
+ /* bus error */
+ sysmmu_debug(3, "irq:bus error\n");
+ break;
+ case 0x10:
+ /* AR security protection fault */
+ sysmmu_debug(3, "irq:ar security protection fault\n");
+ break;
+ case 0x20:
+ /* AR access protection fault */
+ sysmmu_debug(3, "irq:ar access protection fault\n");
+ break;
+ case 0x40:
+ /* AW security protection fault */
+ sysmmu_debug(3, "irq:aw security protection fault\n");
+ break;
+ case 0x80:
+ /* AW access protection fault */
+ sysmmu_debug(3, "irq:aw access protection fault\n");
+ break;
+ }
+ writel(reg_INT_STATUS, sysmmu->regs + S5P_INT_CLEAR);
+ }
+ return IRQ_HANDLED;
+}
+
+static int s5p_sysmmu_probe(struct platform_device *pdev)
+{
+ struct s5p_sysmmu_info *sysmmu;
+ struct resource *res;
+ int ret;
+ unsigned long flags;
+
+ sysmmu = kzalloc(sizeof(struct s5p_sysmmu_info), GFP_KERNEL);
+ if (!sysmmu) {
+ dev_err(&pdev->dev, "no memory for state\n");
+ return -ENOMEM;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (NULL == res) {
+ dev_err(&pdev->dev, "cannot find IO resource\n");
+ ret = -ENOENT;
+ goto err_s5p_sysmmu_info_allocated;
+ }
+
+ sysmmu->ioarea = request_mem_region(res->start, resource_size(res),
+ pdev->name);
+
+ if (NULL == sysmmu->ioarea) {
+ dev_err(&pdev->dev, "cannot request IO\n");
+ ret = -ENXIO;
+ goto err_s5p_sysmmu_info_allocated;
+ }
+
+ sysmmu->regs = ioremap(res->start, resource_size(res));
+
+ if (NULL == sysmmu->regs) {
+ dev_err(&pdev->dev, "cannot map IO\n");
+ ret = -ENXIO;
+ goto err_ioarea_requested;
+ }
+
+ dev_dbg(&pdev->dev, "registers %p (%p, %p)\n",
+ sysmmu->regs, sysmmu->ioarea, res);
+
+ sysmmu->irq = ret = platform_get_irq(pdev, 0);
+ if (ret <= 0) {
+ dev_err(&pdev->dev, "cannot find IRQ\n");
+ goto err_iomap_done;
+ }
+
+ ret = request_irq(sysmmu->irq, s5p_sysmmu_irq, 0,
+ dev_name(&pdev->dev), sysmmu);
+
+ if (ret != 0) {
+ dev_err(&pdev->dev, "cannot claim IRQ %d\n", sysmmu->irq);
+ goto err_iomap_done;
+ }
+
+ sysmmu->clk = clk_get(&pdev->dev, "sysmmu");
+ if (IS_ERR_OR_NULL(sysmmu->clk)) {
+ dev_err(&pdev->dev, "cannot get clock\n");
+ ret = -ENOENT;
+ goto err_request_irq_done;
+ }
+ dev_dbg(&pdev->dev, "clock source %p\n", sysmmu->clk);
+ clk_enable(sysmmu->clk);
+
+ sysmmu->ip = pdev->id;
+
+ spin_lock_irqsave(&sysmmu_list_slock, flags);
+ list_add(&sysmmu->entry, &sysmmu_list);
+ spin_unlock_irqrestore(&sysmmu_list_slock, flags);
+
+ sysmmu->dev = &pdev->dev;
+
+ mutex_init(&sysmmu->mutex);
+
+ platform_set_drvdata(pdev, sysmmu);
+
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+
+ dev_info(&pdev->dev, "Samsung S5P SYSMMU (IOMMU)\n");
+ return 0;
+
+err_request_irq_done:
+ free_irq(sysmmu->irq, sysmmu);
+
+err_iomap_done:
+ iounmap(sysmmu->regs);
+
+err_ioarea_requested:
+ release_resource(sysmmu->ioarea);
+ kfree(sysmmu->ioarea);
+
+err_s5p_sysmmu_info_allocated:
+ kfree(sysmmu);
+ return ret;
+}
+
+static int s5p_sysmmu_remove(struct platform_device *pdev)
+{
+ struct s5p_sysmmu_info *sysmmu = platform_get_drvdata(pdev);
+ unsigned long flags;
+ int i = 1024;
+
+ pm_runtime_disable(sysmmu->dev);
+
+ if ((S5P_SYSMMU_ENABLE_PRIVATE == sysmmu->mode)) {
+ while (i >= 0) {
+ if (sysmmu->refcount[i]) {
+ unsigned long flpt_entry;
+ flpt_entry = dereference_vaddr(
+ sysmmu->flpt_vaddr + 4 * 4 * i);
+ dma_free_coherent(sysmmu->dev,
+ PAGE_SIZE,
+ (void *)sysmmu->vaddr[i],
+ flpt_entry & ~0xFFF);
+ }
+ --i;
+ }
+
+ if (sysmmu->flpt) {
+ dma_free_coherent(sysmmu->dev, 4 * PAGE_SIZE,
+ (void *)sysmmu->flpt_vaddr, sysmmu->flpt);
+ }
+ kfree(sysmmu->refcount);
+ kfree(sysmmu->vaddr);
+ }
+
+ spin_lock_irqsave(&sysmmu_list_slock, flags);
+ list_del(&sysmmu->entry);
+ spin_unlock_irqrestore(&sysmmu_list_slock, flags);
+
+ clk_disable(sysmmu->clk);
+ clk_put(sysmmu->clk);
+
+ free_irq(sysmmu->irq, sysmmu);
+
+ iounmap(sysmmu->regs);
+
+ release_resource(sysmmu->ioarea);
+ kfree(sysmmu->ioarea);
+
+ kfree(sysmmu);
+
+ return 0;
+}
+
+static int s5p_sysmmu_runtime_suspend(struct device *dev)
+{
+ return 0;
+}
+
+static int s5p_sysmmu_runtime_resume(struct device *dev)
+{
+ return 0;
+}
+
+static int s5p_sysmmu_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ return 0;
+}
+
+static int s5p_sysmmu_resume(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static const struct dev_pm_ops s5p_sysmmu_pm_ops = {
+ .runtime_suspend = s5p_sysmmu_runtime_suspend,
+ .runtime_resume = s5p_sysmmu_runtime_resume,
+};
+
+static struct platform_driver s5p_sysmmu_driver = {
+ .probe = s5p_sysmmu_probe,
+ .remove = s5p_sysmmu_remove,
+ .suspend = s5p_sysmmu_suspend,
+ .resume = s5p_sysmmu_resume,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "s5p-sysmmu",
+ .pm = &s5p_sysmmu_pm_ops,
+ },
+};
+
+static int __init s5p_sysmmu_register(void)
+{
+ return platform_driver_register(&s5p_sysmmu_driver);
+}
+
+static void __exit s5p_sysmmu_unregister(void)
+{
+ platform_driver_unregister(&s5p_sysmmu_driver);
+}
+
+module_init(s5p_sysmmu_register);
+module_exit(s5p_sysmmu_unregister);
+
+MODULE_AUTHOR("Andrzej Pietrasiewicz <andrzej.p@samsung.com>");
+MODULE_DESCRIPTION("Samsung System MMU (IOMMU) driver");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h
index b0123f3..9f42dee 100644
--- a/arch/arm/plat-samsung/include/plat/devs.h
+++ b/arch/arm/plat-samsung/include/plat/devs.h
@@ -138,7 +138,7 @@ extern struct platform_device s5p_device_fimc3;
extern struct platform_device s5p_device_mipi_csis0;
extern struct platform_device s5p_device_mipi_csis1;
-extern struct platform_device s5pv310_device_sysmmu;
+extern struct platform_device s5pv310_device_sysmmu[];
/* s3c2440 specific devices */
--
1.7.1.569.g6f426
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH 4/7] v4l: videobuf2: add Samsung SYSMMU (IOMMU) based allocator
2011-03-04 9:01 [PATCH/RFC 0/7] Samsung IOMMU videobuf2 allocator and s5p-fimc update Marek Szyprowski
` (2 preceding siblings ...)
2011-03-04 9:01 ` [PATCH 3/7] ARM: Samsung: update/rewrite Samsung SYSMMU (IOMMU) driver Marek Szyprowski
@ 2011-03-04 9:01 ` Marek Szyprowski
2011-03-04 9:01 ` [PATCH 5/7] s5p-fimc: add pm_runtime support Marek Szyprowski
` (3 subsequent siblings)
7 siblings, 0 replies; 29+ messages in thread
From: Marek Szyprowski @ 2011-03-04 9:01 UTC (permalink / raw)
To: linux-arm-kernel
From: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
This patch adds new videobuf2 memory allocator dedicated to Samsung SoC
series with IOMMU module. It requires s5p-sysmmu low level driver for
controlling iommu. This allocator aquires memory with standard
alloc_page() call and doesn't suffer from memory fragmentation issues.
Curretnly it supports only iommu module on Sasmung S5PV310 SoC series.
Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
drivers/media/video/Kconfig | 8 +-
drivers/media/video/Makefile | 1 +
drivers/media/video/videobuf2-s5p-iommu.c | 444 +++++++++++++++++++++++++++++
include/media/videobuf2-s5p-iommu.h | 50 ++++
4 files changed, 502 insertions(+), 1 deletions(-)
create mode 100644 drivers/media/video/videobuf2-s5p-iommu.c
create mode 100644 include/media/videobuf2-s5p-iommu.h
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index e2f5a69..9806505 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -60,12 +60,18 @@ config VIDEOBUF2_VMALLOC
select VIDEOBUF2_MEMOPS
tristate
-
config VIDEOBUF2_DMA_SG
#depends on HAS_DMA
select VIDEOBUF2_CORE
select VIDEOBUF2_MEMOPS
tristate
+
+config VIDEOBUF2_S5P_IOMMU
+ select GENERIC_ALLOCATOR
+ select VIDEOBUF2_CORE
+ select VIDEOBUF2_MEMOPS
+ tristate
+
#
# Multimedia Video device configuration
#
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index ac54652..fd9488d 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -118,6 +118,7 @@ obj-$(CONFIG_VIDEOBUF2_MEMOPS) += videobuf2-memops.o
obj-$(CONFIG_VIDEOBUF2_VMALLOC) += videobuf2-vmalloc.o
obj-$(CONFIG_VIDEOBUF2_DMA_CONTIG) += videobuf2-dma-contig.o
obj-$(CONFIG_VIDEOBUF2_DMA_SG) += videobuf2-dma-sg.o
+obj-$(CONFIG_VIDEOBUF2_S5P_IOMMU) += videobuf2-s5p-iommu.o
obj-$(CONFIG_V4L2_MEM2MEM_DEV) += v4l2-mem2mem.o
diff --git a/drivers/media/video/videobuf2-s5p-iommu.c b/drivers/media/video/videobuf2-s5p-iommu.c
new file mode 100644
index 0000000..5826fe0
--- /dev/null
+++ b/drivers/media/video/videobuf2-s5p-iommu.c
@@ -0,0 +1,444 @@
+/*
+ * videobuf2-s5p-iommu.c - SYSMMU (IOMMU) based memory allocator for videobuf2
+ *
+ * Copyright (C) 2011 Samsung Electronics
+ *
+ * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/scatterlist.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/genalloc.h>
+#include <linux/device.h>
+#include <asm/cacheflush.h>
+#include <asm/page.h>
+
+#include <media/videobuf2-core.h>
+#include <media/videobuf2-memops.h>
+#include <media/videobuf2-s5p-iommu.h>
+
+/*
+ * 17: single piece of memory (one bitmap entry) equals 128k,
+ * so by default the genalloc's bitmap occupies 4kB (one page
+ * for a number of architectures)
+ */
+#define VB2_S5P_IOMMU_PIECE_ORDER 17
+
+/* -1: use default node id to allocate gen_pool/gen_pool_chunk structure from */
+#define VB2_S5P_IOMMU_NODE_ID -1
+
+/*
+ * starting address of the virtual address space of the client device
+ * must not be zero
+ */
+#define VB2_S5P_IOMMU_MEM_BASE 0x30000000
+
+/* size of the virtual address space of the client device */
+#define VB2_S5P_IOMMU_MEM_SIZE 0x40000000
+
+struct vb2_s5p_iommu_alloc_ctx {
+ /* not interpreted here; only passed to the sysmmu driver */
+ void *sysmmu;
+
+ struct gen_pool *pool;
+};
+
+struct vb2_s5p_iommu_desc {
+ unsigned long size;
+ unsigned int num_pages;
+ struct page **pages;
+};
+
+struct vb2_s5p_iommu_buf {
+ unsigned long drv_addr;
+ unsigned long vaddr;
+
+ struct vb2_s5p_iommu_desc info;
+ int offset;
+ atomic_t refcount;
+ int write;
+ struct vm_area_struct *vma;
+
+ struct vb2_vmarea_handler handler;
+
+ struct vb2_s5p_iommu_alloc_ctx *ctx;
+};
+
+static void vb2_s5p_iommu_put(void *buf_priv);
+
+static void *vb2_s5p_iommu_alloc(void *alloc_ctx, unsigned long size)
+{
+ struct vb2_s5p_iommu_alloc_ctx *ctx = alloc_ctx;
+ struct vb2_s5p_iommu_buf *buf;
+ int i, ret;
+
+ BUG_ON(NULL == alloc_ctx);
+
+ buf = kzalloc(sizeof *buf, GFP_KERNEL);
+ if (!buf)
+ return NULL;
+
+ buf->drv_addr = gen_pool_alloc(ctx->pool, size);
+ if (0 == buf->drv_addr)
+ goto gen_pool_alloc_fail;
+
+ buf->info.size = size;
+ buf->info.num_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ buf->ctx = ctx;
+ buf->info.pages = kzalloc(
+ buf->info.num_pages * sizeof(struct page *), GFP_KERNEL);
+ if (!buf->info.pages)
+ goto fail_pages_array_alloc;
+
+ for (i = 0; i < buf->info.num_pages; ++i) {
+ buf->info.pages[i] = alloc_page(GFP_KERNEL | __GFP_ZERO);
+ if (NULL == buf->info.pages[i])
+ goto fail_pages_alloc;
+ }
+
+ buf->handler.refcount = &buf->refcount;
+ buf->handler.put = vb2_s5p_iommu_put;
+ buf->handler.arg = buf;
+
+ atomic_inc(&buf->refcount);
+
+ ret = s5p_sysmmu_map_area(ctx->sysmmu, buf->drv_addr,
+ buf->info.num_pages, buf->info.pages);
+
+ if (ret < 0)
+ goto fail_sysmmu_map_area;
+
+ /*
+ * TODO: Ensure no one else flushes the cache later onto our memory
+ * which already contains important data.
+ * Perhaps find a better way to do it.
+ */
+ flush_cache_all();
+ outer_flush_all();
+ return buf;
+
+fail_sysmmu_map_area:
+fail_pages_alloc:
+ while (--i >= 0)
+ __free_page(buf->info.pages[i]);
+ kfree(buf->info.pages);
+
+fail_pages_array_alloc:
+ gen_pool_free(ctx->pool, buf->drv_addr, size);
+
+gen_pool_alloc_fail:
+ kfree(buf);
+ return NULL;
+}
+
+static void vb2_s5p_iommu_put(void *buf_priv)
+{
+ struct vb2_s5p_iommu_buf *buf = buf_priv;
+ int i = buf->info.num_pages;
+
+ if (atomic_dec_and_test(&buf->refcount)) {
+ s5p_sysmmu_unmap_area(buf->ctx->sysmmu, buf->drv_addr,
+ buf->info.num_pages);
+ if (buf->vaddr)
+ vm_unmap_ram((void *)buf->vaddr, buf->info.num_pages);
+ while (--i >= 0)
+ __free_page(buf->info.pages[i]);
+ kfree(buf->info.pages);
+ gen_pool_free(buf->ctx->pool, buf->drv_addr, buf->info.size);
+ kfree(buf);
+ }
+}
+
+static void *vb2_s5p_iommu_get_userptr(void *alloc_ctx, unsigned long vaddr,
+ unsigned long size, int write)
+{
+ struct vb2_s5p_iommu_alloc_ctx *ctx = alloc_ctx;
+ struct vb2_s5p_iommu_buf *buf;
+ unsigned long first, last;
+ int num_pages_from_user, ret;
+ void *rv = NULL;
+
+ BUG_ON(NULL == alloc_ctx);
+
+ buf = kzalloc(sizeof *buf, GFP_KERNEL);
+ if (!buf)
+ return rv;
+
+ buf->drv_addr = gen_pool_alloc(ctx->pool, size);
+ if (0 == buf->drv_addr) {
+ rv = ERR_PTR(-ENOMEM);
+ goto userptr_gen_pool_alloc_fail;
+ }
+
+ buf->write = write;
+ buf->offset = vaddr & ~PAGE_MASK;
+ buf->info.size = size;
+ first = (vaddr & PAGE_MASK) >> PAGE_SHIFT;
+ last = ((vaddr + size - 1) & PAGE_MASK) >> PAGE_SHIFT;
+ buf->info.num_pages = last - first + 1;
+ buf->ctx = ctx;
+ buf->info.pages = kzalloc(buf->info.num_pages * sizeof(struct page *),
+ GFP_KERNEL);
+ if (!buf->info.pages) {
+ rv = ERR_PTR(-ENOMEM);
+ goto userptr_fail_pages_array_alloc;
+ }
+
+ down_read(¤t->mm->mmap_sem);
+ num_pages_from_user = get_user_pages(current, current->mm,
+ vaddr & PAGE_MASK,
+ buf->info.num_pages,
+ write,
+ 1, /* force */
+ buf->info.pages,
+ NULL);
+ up_read(¤t->mm->mmap_sem);
+
+ if (num_pages_from_user == buf->info.num_pages) {
+ ret = s5p_sysmmu_map_area(ctx->sysmmu, buf->drv_addr,
+ buf->info.num_pages, buf->info.pages);
+
+ if (ret)
+ goto userptr_fail_sysmmu_map_area;
+
+ return buf;
+ } else if (num_pages_from_user < 0) {
+ struct vm_area_struct *vma;
+ dma_addr_t paddr = 0;
+
+ ret = vb2_get_contig_userptr(vaddr, size, &vma, &paddr);
+
+ if (ret) {
+ rv = ERR_PTR(ret);
+ goto userptr_fail_get_contig;
+ }
+
+ buf->vma = vma;
+
+ ret = s5p_sysmmu_map_phys_area(ctx->sysmmu, buf->drv_addr,
+ paddr, buf->info.num_pages);
+ if (ret)
+ goto userptr_fail_sysmmu_map_area;
+
+ return buf;
+ }
+ /* else fail */
+
+userptr_fail_sysmmu_map_area:
+ while (--num_pages_from_user >= 0)
+ put_page(buf->info.pages[num_pages_from_user]);
+ if (buf->vma)
+ vb2_put_vma(buf->vma);
+userptr_fail_get_contig:
+ kfree(buf->info.pages);
+
+userptr_fail_pages_array_alloc:
+ gen_pool_free(ctx->pool, buf->drv_addr, size);
+
+userptr_gen_pool_alloc_fail:
+ kfree(buf);
+ return rv;
+}
+
+/*
+ * @put_userptr: inform the allocator that a USERPTR buffer will no longer
+ * be used
+ */
+static void vb2_s5p_iommu_put_userptr(void *buf_priv)
+{
+ struct vb2_s5p_iommu_buf *buf = buf_priv;
+ int i = buf->info.num_pages;
+
+ printk(KERN_DEBUG "%s: Releasing userspace buffer of %d pages\n",
+ __func__, buf->info.num_pages);
+ if (buf->vaddr)
+ vm_unmap_ram((void *)buf->vaddr, buf->info.num_pages);
+ s5p_sysmmu_unmap_area(buf->ctx->sysmmu, buf->drv_addr,
+ buf->info.num_pages);
+ if (buf->vma) {
+ vb2_put_vma(buf->vma);
+ } else {
+ while (--i >= 0) {
+ if (buf->write)
+ set_page_dirty_lock(buf->info.pages[i]);
+ put_page(buf->info.pages[i]);
+ }
+ }
+ kfree(buf->info.pages);
+ gen_pool_free(buf->ctx->pool, buf->drv_addr, buf->info.size);
+ kfree(buf);
+}
+
+static void *vb2_s5p_iommu_vaddr(void *buf_priv)
+{
+ struct vb2_s5p_iommu_buf *buf = buf_priv;
+
+ BUG_ON(!buf);
+
+ if (!buf->vaddr)
+ buf->vaddr = (unsigned long)vm_map_ram(buf->info.pages,
+ buf->info.num_pages,
+ -1,
+ pgprot_writecombine(PAGE_KERNEL));
+
+ /* add offset in case userptr is not page-aligned */
+ return (void *)(buf->vaddr + buf->offset);
+}
+
+static unsigned int vb2_s5p_iommu_num_users(void *buf_priv)
+{
+ struct vb2_s5p_iommu_buf *buf = buf_priv;
+
+ return atomic_read(&buf->refcount);
+}
+
+static int vb2_s5p_iommu_mmap(void *buf_priv, struct vm_area_struct *vma)
+{
+ struct vb2_s5p_iommu_buf *buf = buf_priv;
+ unsigned long uaddr = vma->vm_start;
+ unsigned long usize = vma->vm_end - vma->vm_start;
+ int i = 0;
+
+ if (!buf) {
+ printk(KERN_ERR "No memory to map\n");
+ return -EINVAL;
+ }
+
+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+ do {
+ int ret;
+
+ ret = vm_insert_page(vma, uaddr, buf->info.pages[i++]);
+ if (ret) {
+ printk(KERN_ERR "Remapping memory, error: %d\n", ret);
+ return ret;
+ }
+
+ uaddr += PAGE_SIZE;
+ usize -= PAGE_SIZE;
+ } while (usize > 0);
+
+
+ /*
+ * Use common vm_area operations to track buffer refcount.
+ */
+ vma->vm_private_data = &buf->handler;
+ vma->vm_ops = &vb2_common_vm_ops;
+
+ vma->vm_ops->open(vma);
+
+ return 0;
+}
+
+static void *vb2_s5p_iommu_cookie(void *buf_priv)
+{
+ struct vb2_s5p_iommu_buf *buf = buf_priv;
+
+ return (void *)buf->drv_addr + buf->offset;
+}
+
+const struct vb2_mem_ops vb2_s5p_iommu_memops = {
+ .alloc = vb2_s5p_iommu_alloc,
+ .put = vb2_s5p_iommu_put,
+ .get_userptr = vb2_s5p_iommu_get_userptr,
+ .put_userptr = vb2_s5p_iommu_put_userptr,
+ .vaddr = vb2_s5p_iommu_vaddr,
+ .mmap = vb2_s5p_iommu_mmap,
+ .num_users = vb2_s5p_iommu_num_users,
+ .cookie = vb2_s5p_iommu_cookie,
+};
+EXPORT_SYMBOL_GPL(vb2_s5p_iommu_memops);
+
+void
+*vb2_s5p_iommu_init(struct device *dev, struct vb2_s5p_iommu_request *iommu_req)
+{
+ struct vb2_s5p_iommu_alloc_ctx *ctx;
+ unsigned long mem_base, mem_size;
+
+ ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
+ if (!ctx)
+ return ERR_PTR(-ENOMEM);
+
+ if (iommu_req->align_order && iommu_req->align_order < PAGE_SHIFT)
+ iommu_req->align_order = PAGE_SHIFT;
+
+ ctx->pool = gen_pool_create(
+ iommu_req->align_order ? iommu_req->align_order :
+ VB2_S5P_IOMMU_PIECE_ORDER,
+ VB2_S5P_IOMMU_NODE_ID);
+
+ if (!ctx->pool)
+ goto pool_alloc_fail;
+
+ if (0 == iommu_req->mem_base && 0 == iommu_req->mem_size) {
+ mem_base = VB2_S5P_IOMMU_MEM_BASE;
+ mem_size = VB2_S5P_IOMMU_MEM_SIZE;
+ } else {
+ mem_base = iommu_req->mem_base;
+ mem_size = iommu_req->mem_size;
+ }
+
+ if (gen_pool_add(ctx->pool, mem_base, mem_size, VB2_S5P_IOMMU_NODE_ID))
+ goto chunk_add_fail;
+
+ ctx->sysmmu = s5p_sysmmu_get(dev, iommu_req->ip);
+ if (!ctx->sysmmu) {
+ dev_err(dev, "SYSMMU get failed\n");
+ goto chunk_add_fail;
+ }
+
+ return ctx;
+
+chunk_add_fail:
+ gen_pool_destroy(ctx->pool);
+pool_alloc_fail:
+ kfree(ctx);
+ return ERR_PTR(-ENOMEM);
+}
+EXPORT_SYMBOL_GPL(vb2_s5p_iommu_init);
+
+void vb2_s5p_iommu_cleanup(void *alloc_ctx)
+{
+ struct vb2_s5p_iommu_alloc_ctx *ctx = alloc_ctx;
+
+ BUG_ON(NULL == alloc_ctx);
+
+ s5p_sysmmu_put(ctx->sysmmu);
+
+ gen_pool_destroy(ctx->pool);
+
+ kfree(alloc_ctx);
+}
+EXPORT_SYMBOL_GPL(vb2_s5p_iommu_cleanup);
+
+int vb2_s5p_iommu_enable(void *alloc_ctx)
+{
+ struct vb2_s5p_iommu_alloc_ctx *ctx = alloc_ctx;
+
+ BUG_ON(NULL == alloc_ctx);
+
+ return s5p_sysmmu_control(ctx->sysmmu, S5P_SYSMMU_ENABLE_PRIVATE);
+}
+EXPORT_SYMBOL_GPL(vb2_s5p_iommu_enable);
+
+int vb2_s5p_iommu_disable(void *alloc_ctx)
+{
+ struct vb2_s5p_iommu_alloc_ctx *ctx = alloc_ctx;
+
+ BUG_ON(NULL == alloc_ctx);
+
+ return s5p_sysmmu_control(ctx->sysmmu, S5P_SYSMMU_DISABLE);
+}
+EXPORT_SYMBOL_GPL(vb2_s5p_iommu_disable);
+
+MODULE_DESCRIPTION("s5p iommu memory handling routines for videobuf2");
+MODULE_AUTHOR("Andrzej Pietrasiewicz");
+MODULE_LICENSE("GPL");
diff --git a/include/media/videobuf2-s5p-iommu.h b/include/media/videobuf2-s5p-iommu.h
new file mode 100644
index 0000000..5bad763
--- /dev/null
+++ b/include/media/videobuf2-s5p-iommu.h
@@ -0,0 +1,50 @@
+/*
+ * videobuf2-s5p-iommu.h - SYSMMU (IOMMU)-based memory allocator for videobuf2
+ *
+ * Copyright (C) 2011 Samsung Electronics
+ *
+ * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ */
+
+#ifndef _MEDIA_VIDEOBUF2_S5P_IOMMU_H
+#define _MEDIA_VIDEOBUF2_S5P_IOMMU_H
+
+#include <media/videobuf2-core.h>
+#include <plat/sysmmu.h>
+
+struct device;
+
+struct vb2_s5p_iommu_request {
+ /* mem_base and mem_size both 0 => use allocator's default */
+ unsigned long mem_base;
+ unsigned long mem_size;
+ enum s5p_sysmmu_ip ip;
+ /*
+ * align_order 0 => use allocator's default
+ * 0 < align_order < PAGE_SHIFT => rounded to PAGE_SHIFT by allocator
+ */
+ int align_order;
+};
+
+static inline unsigned long vb2_s5p_iommu_plane_addr(
+ struct vb2_buffer *vb, unsigned int plane_no)
+{
+ return (unsigned long)vb2_plane_cookie(vb, plane_no);
+}
+
+extern const struct vb2_mem_ops vb2_s5p_iommu_memops;
+
+void *vb2_s5p_iommu_init(struct device *dev,
+ struct vb2_s5p_iommu_request *iommu_req);
+
+void vb2_s5p_iommu_cleanup(void *alloc_ctx);
+
+int vb2_s5p_iommu_enable(void *alloc_ctx);
+
+int vb2_s5p_iommu_disable(void *alloc_ctx);
+
+#endif
--
1.7.1.569.g6f426
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH 5/7] s5p-fimc: add pm_runtime support
2011-03-04 9:01 [PATCH/RFC 0/7] Samsung IOMMU videobuf2 allocator and s5p-fimc update Marek Szyprowski
` (3 preceding siblings ...)
2011-03-04 9:01 ` [PATCH 4/7] v4l: videobuf2: add Samsung SYSMMU (IOMMU) based allocator Marek Szyprowski
@ 2011-03-04 9:01 ` Marek Szyprowski
2011-03-04 9:01 ` [PATCH 6/7] s5p-fimc: Add support for vb2-s5p-iommu allocator Marek Szyprowski
` (2 subsequent siblings)
7 siblings, 0 replies; 29+ messages in thread
From: Marek Szyprowski @ 2011-03-04 9:01 UTC (permalink / raw)
To: linux-arm-kernel
This patch adds basic support for pm_runtime to s5p-fimc driver. PM
runtime support is required to enable the driver on S5PV310 series with
power domain driver enabled.
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
drivers/media/video/s5p-fimc/fimc-capture.c | 5 +++++
drivers/media/video/s5p-fimc/fimc-core.c | 14 ++++++++++++++
2 files changed, 19 insertions(+), 0 deletions(-)
diff --git a/drivers/media/video/s5p-fimc/fimc-capture.c b/drivers/media/video/s5p-fimc/fimc-capture.c
index 59123a6..f8d7de5 100644
--- a/drivers/media/video/s5p-fimc/fimc-capture.c
+++ b/drivers/media/video/s5p-fimc/fimc-capture.c
@@ -18,6 +18,7 @@
#include <linux/interrupt.h>
#include <linux/device.h>
#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
#include <linux/list.h>
#include <linux/slab.h>
#include <linux/clk.h>
@@ -395,6 +396,8 @@ static int fimc_capture_open(struct file *file)
if (fimc_m2m_active(fimc))
return -EBUSY;
+ pm_runtime_get_sync(&fimc->pdev->dev);
+
if (++fimc->vid_cap.refcnt == 1) {
ret = fimc_isp_subdev_init(fimc, 0);
if (ret) {
@@ -425,6 +428,8 @@ static int fimc_capture_close(struct file *file)
fimc_subdev_unregister(fimc);
}
+ pm_runtime_put_sync(&fimc->pdev->dev);
+
return 0;
}
diff --git a/drivers/media/video/s5p-fimc/fimc-core.c b/drivers/media/video/s5p-fimc/fimc-core.c
index db3e730..c92dbdb 100644
--- a/drivers/media/video/s5p-fimc/fimc-core.c
+++ b/drivers/media/video/s5p-fimc/fimc-core.c
@@ -20,6 +20,7 @@
#include <linux/interrupt.h>
#include <linux/device.h>
#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
#include <linux/list.h>
#include <linux/io.h>
#include <linux/slab.h>
@@ -1407,6 +1408,8 @@ static int fimc_m2m_open(struct file *file)
if (fimc->vid_cap.refcnt > 0)
return -EBUSY;
+ pm_runtime_get_sync(&fimc->pdev->dev);
+
fimc->m2m.refcnt++;
set_bit(ST_OUTDMA_RUN, &fimc->state);
@@ -1449,6 +1452,8 @@ static int fimc_m2m_release(struct file *file)
if (--fimc->m2m.refcnt <= 0)
clear_bit(ST_OUTDMA_RUN, &fimc->state);
+ pm_runtime_put_sync(&fimc->pdev->dev);
+
return 0;
}
@@ -1646,6 +1651,11 @@ static int fimc_probe(struct platform_device *pdev)
goto err_req_region;
}
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+
+ pm_runtime_get_sync(&pdev->dev);
+
fimc->num_clocks = MAX_FIMC_CLOCKS - 1;
/* Check if a video capture node needs to be registered. */
@@ -1703,6 +1713,8 @@ static int fimc_probe(struct platform_device *pdev)
dev_dbg(&pdev->dev, "%s(): fimc-%d registered successfully\n",
__func__, fimc->id);
+ pm_runtime_put_sync(&pdev->dev);
+
return 0;
err_m2m:
@@ -1737,6 +1749,8 @@ static int __devexit fimc_remove(struct platform_device *pdev)
vb2_dma_contig_cleanup_ctx(fimc->alloc_ctx);
+ pm_runtime_disable(&pdev->dev);
+
iounmap(fimc->regs);
release_resource(fimc->regs_res);
kfree(fimc->regs_res);
--
1.7.1.569.g6f426
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH 6/7] s5p-fimc: Add support for vb2-s5p-iommu allocator
2011-03-04 9:01 [PATCH/RFC 0/7] Samsung IOMMU videobuf2 allocator and s5p-fimc update Marek Szyprowski
` (4 preceding siblings ...)
2011-03-04 9:01 ` [PATCH 5/7] s5p-fimc: add pm_runtime support Marek Szyprowski
@ 2011-03-04 9:01 ` Marek Szyprowski
2011-03-04 9:01 ` [PATCH 7/7] ARM: S5PC210: enable FIMC on Universal_C210 Marek Szyprowski
2011-03-08 7:28 ` [PATCH/RFC 0/7] Samsung IOMMU videobuf2 allocator and s5p-fimc update Kukjin Kim
7 siblings, 0 replies; 29+ messages in thread
From: Marek Szyprowski @ 2011-03-04 9:01 UTC (permalink / raw)
To: linux-arm-kernel
This patch adds support for videobuf2-s5p-iommu allocator to s5p-fimc
driver. This allocator is selected only on systems that contains support
for S5P SYSMMU module. Otherwise the standard videobuf2-dma-contig is
used.
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
drivers/media/video/Kconfig | 3 +-
drivers/media/video/s5p-fimc/fimc-capture.c | 4 +-
drivers/media/video/s5p-fimc/fimc-core.c | 22 ++++---
drivers/media/video/s5p-fimc/fimc-mem.h | 87 +++++++++++++++++++++++++++
4 files changed, 104 insertions(+), 12 deletions(-)
create mode 100644 drivers/media/video/s5p-fimc/fimc-mem.h
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index 9806505..12fb325 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -1018,7 +1018,8 @@ config VIDEO_MEM2MEM_TESTDEV
config VIDEO_SAMSUNG_S5P_FIMC
tristate "Samsung S5P FIMC (video postprocessor) driver"
depends on VIDEO_DEV && VIDEO_V4L2 && PLAT_S5P
- select VIDEOBUF2_DMA_CONTIG
+ select VIDEOBUF2_S5P_IOMMU if S5P_SYSTEM_MMU
+ select VIDEOBUF2_DMA_CONTIG if !S5P_SYSTEM_MMU
select V4L2_MEM2MEM_DEV
help
This is a v4l2 driver for the S5P camera interface
diff --git a/drivers/media/video/s5p-fimc/fimc-capture.c b/drivers/media/video/s5p-fimc/fimc-capture.c
index f8d7de5..6819908 100644
--- a/drivers/media/video/s5p-fimc/fimc-capture.c
+++ b/drivers/media/video/s5p-fimc/fimc-capture.c
@@ -29,8 +29,8 @@
#include <media/v4l2-ioctl.h>
#include <media/v4l2-mem2mem.h>
#include <media/videobuf2-core.h>
-#include <media/videobuf2-dma-contig.h>
+#include "fimc-mem.h"
#include "fimc-core.h"
static struct v4l2_subdev *fimc_subdev_register(struct fimc_dev *fimc,
@@ -881,7 +881,7 @@ int fimc_register_capture_device(struct fimc_dev *fimc)
q->io_modes = VB2_MMAP | VB2_USERPTR;
q->drv_priv = fimc->vid_cap.ctx;
q->ops = &fimc_capture_qops;
- q->mem_ops = &vb2_dma_contig_memops;
+ q->mem_ops = &fimc_vb2_allocator_memops;
q->buf_struct_size = sizeof(struct fimc_vid_buffer);
vb2_queue_init(q);
diff --git a/drivers/media/video/s5p-fimc/fimc-core.c b/drivers/media/video/s5p-fimc/fimc-core.c
index c92dbdb..f06aaea 100644
--- a/drivers/media/video/s5p-fimc/fimc-core.c
+++ b/drivers/media/video/s5p-fimc/fimc-core.c
@@ -27,8 +27,8 @@
#include <linux/clk.h>
#include <media/v4l2-ioctl.h>
#include <media/videobuf2-core.h>
-#include <media/videobuf2-dma-contig.h>
+#include "fimc-mem.h"
#include "fimc-core.h"
static char *fimc_clocks[MAX_FIMC_CLOCKS] = {
@@ -458,7 +458,7 @@ int fimc_prepare_addr(struct fimc_ctx *ctx, struct vb2_buffer *vb,
dbg("memplanes= %d, colplanes= %d, pix_size= %d",
frame->fmt->memplanes, frame->fmt->colplanes, pix_size);
- paddr->y = vb2_dma_contig_plane_paddr(vb, 0);
+ paddr->y = fimc_vb2_plane_addr(vb, 0);
if (frame->fmt->memplanes == 1) {
switch (frame->fmt->colplanes) {
@@ -486,10 +486,10 @@ int fimc_prepare_addr(struct fimc_ctx *ctx, struct vb2_buffer *vb,
}
} else {
if (frame->fmt->memplanes >= 2)
- paddr->cb = vb2_dma_contig_plane_paddr(vb, 1);
+ paddr->cb = fimc_vb2_plane_addr(vb, 1);
if (frame->fmt->memplanes == 3)
- paddr->cr = vb2_dma_contig_plane_paddr(vb, 2);
+ paddr->cr = fimc_vb2_plane_addr(vb, 2);
}
dbg("PHYS_ADDR: y= 0x%X cb= 0x%X cr= 0x%X ret= %d",
@@ -1375,7 +1375,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq,
src_vq->io_modes = VB2_MMAP | VB2_USERPTR;
src_vq->drv_priv = ctx;
src_vq->ops = &fimc_qops;
- src_vq->mem_ops = &vb2_dma_contig_memops;
+ src_vq->mem_ops = &fimc_vb2_allocator_memops;
src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
ret = vb2_queue_init(src_vq);
@@ -1387,7 +1387,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq,
dst_vq->io_modes = VB2_MMAP | VB2_USERPTR;
dst_vq->drv_priv = ctx;
dst_vq->ops = &fimc_qops;
- dst_vq->mem_ops = &vb2_dma_contig_memops;
+ dst_vq->mem_ops = &fimc_vb2_allocator_memops;
dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
return vb2_queue_init(dst_vq);
@@ -1685,12 +1685,15 @@ static int fimc_probe(struct platform_device *pdev)
goto err_clk;
}
- /* Initialize contiguous memory allocator */
- fimc->alloc_ctx = vb2_dma_contig_init_ctx(&fimc->pdev->dev);
+ /* Initialize memory allocator */
+ fimc->alloc_ctx = fimc_vb2_allocator_init(pdev);
if (IS_ERR(fimc->alloc_ctx)) {
ret = PTR_ERR(fimc->alloc_ctx);
goto err_irq;
}
+ ret = fimc_vb2_allocator_enable(fimc->alloc_ctx);
+ if (ret)
+ goto err_irq;
ret = fimc_register_m2m_device(fimc);
if (ret)
@@ -1747,7 +1750,8 @@ static int __devexit fimc_remove(struct platform_device *pdev)
fimc_clk_release(fimc);
- vb2_dma_contig_cleanup_ctx(fimc->alloc_ctx);
+ fimc_vb2_allocator_disable(fimc->alloc_ctx);
+ fimc_vb2_allocator_cleanup(fimc->alloc_ctx);
pm_runtime_disable(&pdev->dev);
diff --git a/drivers/media/video/s5p-fimc/fimc-mem.h b/drivers/media/video/s5p-fimc/fimc-mem.h
new file mode 100644
index 0000000..9ac9bc6
--- /dev/null
+++ b/drivers/media/video/s5p-fimc/fimc-mem.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef FIMC_MEM_H_
+#define FIMC_MEM_H_
+
+/*
+ * fimc-mem.h is the interface for videbuf2 allocator. It is a proxy
+ * to real allocator depending on system capabilities.
+ * 1. on S5PC100 & S5PV210/S5PC110 systems vb2-dma-contig is used
+ * 2. on S5PV310/S5PC210 systems vb2-s5p-iommu allocator is selected.
+ *
+ */
+
+#ifdef CONFIG_S5P_SYSTEM_MMU
+
+#include <media/videobuf2-s5p-iommu.h>
+
+#define fimc_vb2_allocator_memops vb2_s5p_iommu_memops
+
+static inline void *fimc_vb2_allocator_init(struct platform_device *pdev)
+{
+ struct vb2_s5p_iommu_request iommu_req;
+ memset(&iommu_req, 0, sizeof(iommu_req));
+ iommu_req.ip = S5P_SYSMMU_FIMC0 + pdev->id;
+ return vb2_s5p_iommu_init(&pdev->dev, &iommu_req);
+}
+
+static inline void fimc_vb2_allocator_cleanup(void *alloc_ctx)
+{
+ return vb2_s5p_iommu_cleanup(alloc_ctx);
+}
+
+static inline unsigned long fimc_vb2_plane_addr(struct vb2_buffer *b, int n)
+{
+ return vb2_s5p_iommu_plane_addr(b, n);
+}
+
+static inline int fimc_vb2_allocator_enable(void *alloc_ctx)
+{
+ return vb2_s5p_iommu_enable(alloc_ctx);
+}
+
+static inline int fimc_vb2_allocator_disable(void *alloc_ctx)
+{
+ return vb2_s5p_iommu_disable(alloc_ctx);
+}
+
+#else /* use vb2-dma-contig allocator */
+
+#include <media/videobuf2-dma-contig.h>
+
+#define fimc_vb2_allocator_memops vb2_dma_contig_memops
+
+static inline void *fimc_vb2_allocator_init(struct platform_device *pdev)
+{
+ return vb2_dma_contig_init_ctx(&pdev->dev);
+}
+
+static inline void fimc_vb2_allocator_cleanup(void *alloc_ctx)
+{
+ vb2_dma_contig_cleanup_ctx(alloc_ctx);
+}
+
+static inline unsigned long fimc_vb2_plane_addr(struct vb2_buffer *b, int n)
+{
+ return vb2_dma_contig_plane_paddr(b, n);
+}
+
+static inline int fimc_vb2_allocator_enable(void *alloc_ctx)
+{
+ return 0;
+}
+
+static inline int fimc_vb2_allocator_disable(void *alloc_ctx)
+{
+ return 0;
+}
+
+#endif
+
+#endif /* FIMC_CORE_H_ */
--
1.7.1.569.g6f426
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH 7/7] ARM: S5PC210: enable FIMC on Universal_C210
2011-03-04 9:01 [PATCH/RFC 0/7] Samsung IOMMU videobuf2 allocator and s5p-fimc update Marek Szyprowski
` (5 preceding siblings ...)
2011-03-04 9:01 ` [PATCH 6/7] s5p-fimc: Add support for vb2-s5p-iommu allocator Marek Szyprowski
@ 2011-03-04 9:01 ` Marek Szyprowski
2011-03-08 7:28 ` [PATCH/RFC 0/7] Samsung IOMMU videobuf2 allocator and s5p-fimc update Kukjin Kim
7 siblings, 0 replies; 29+ messages in thread
From: Marek Szyprowski @ 2011-03-04 9:01 UTC (permalink / raw)
To: linux-arm-kernel
This patch adds definitions to enable support for s5p-fimc driver
together with required power domains and sysmmu controller on Universal
C210 board.
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
arch/arm/mach-s5pv310/Kconfig | 6 ++++++
arch/arm/mach-s5pv310/mach-universal_c210.c | 20 ++++++++++++++++++++
2 files changed, 26 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-s5pv310/Kconfig b/arch/arm/mach-s5pv310/Kconfig
index a8b0425..c850086 100644
--- a/arch/arm/mach-s5pv310/Kconfig
+++ b/arch/arm/mach-s5pv310/Kconfig
@@ -97,12 +97,18 @@ config MACH_UNIVERSAL_C210
bool "Mobile UNIVERSAL_C210 Board"
select CPU_S5PV310
select S5P_DEV_ONENAND
+ select S5P_DEV_FIMC0
+ select S5P_DEV_FIMC1
+ select S5P_DEV_FIMC2
+ select S5P_DEV_FIMC3
select S3C_DEV_HSMMC
select S3C_DEV_HSMMC2
select S3C_DEV_HSMMC3
select S5PV310_SETUP_SDHCI
select S3C_DEV_I2C1
select S3C_DEV_I2C5
+ select S5PV310_DEV_PD
+ select S5PV310_DEV_SYSMMU
select S5PV310_SETUP_I2C1
select S5PV310_SETUP_I2C5
help
diff --git a/arch/arm/mach-s5pv310/mach-universal_c210.c b/arch/arm/mach-s5pv310/mach-universal_c210.c
index eece381..f153895 100644
--- a/arch/arm/mach-s5pv310/mach-universal_c210.c
+++ b/arch/arm/mach-s5pv310/mach-universal_c210.c
@@ -24,7 +24,9 @@
#include <plat/s5pv310.h>
#include <plat/cpu.h>
#include <plat/devs.h>
+#include <plat/pd.h>
#include <plat/sdhci.h>
+#include <plat/sysmmu.h>
#include <mach/map.h>
#include <mach/gpio.h>
@@ -816,6 +818,15 @@ static struct platform_device *universal_devices[] __initdata = {
&s3c_device_hsmmc0,
&s3c_device_hsmmc2,
&s3c_device_hsmmc3,
+ &s5p_device_fimc0,
+ &s5p_device_fimc1,
+ &s5p_device_fimc2,
+ &s5p_device_fimc3,
+ &s5pv310_device_pd[PD_CAM],
+ &s5pv310_device_sysmmu[S5P_SYSMMU_FIMC0],
+ &s5pv310_device_sysmmu[S5P_SYSMMU_FIMC1],
+ &s5pv310_device_sysmmu[S5P_SYSMMU_FIMC2],
+ &s5pv310_device_sysmmu[S5P_SYSMMU_FIMC3],
/* Universal Devices */
&universal_gpio_keys,
@@ -842,6 +853,15 @@ static void __init universal_machine_init(void)
/* Last */
platform_add_devices(universal_devices, ARRAY_SIZE(universal_devices));
+
+ s5p_device_fimc0.dev.parent = &s5pv310_device_pd[PD_CAM].dev;
+ s5p_device_fimc1.dev.parent = &s5pv310_device_pd[PD_CAM].dev;
+ s5p_device_fimc2.dev.parent = &s5pv310_device_pd[PD_CAM].dev;
+ s5p_device_fimc3.dev.parent = &s5pv310_device_pd[PD_CAM].dev;
+ s5pv310_device_sysmmu[S5P_SYSMMU_FIMC0].dev.parent = &s5pv310_device_pd[PD_CAM].dev;
+ s5pv310_device_sysmmu[S5P_SYSMMU_FIMC1].dev.parent = &s5pv310_device_pd[PD_CAM].dev;
+ s5pv310_device_sysmmu[S5P_SYSMMU_FIMC2].dev.parent = &s5pv310_device_pd[PD_CAM].dev;
+ s5pv310_device_sysmmu[S5P_SYSMMU_FIMC3].dev.parent = &s5pv310_device_pd[PD_CAM].dev;
}
MACHINE_START(UNIVERSAL_C210, "UNIVERSAL_C210")
--
1.7.1.569.g6f426
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH 3/7] ARM: Samsung: update/rewrite Samsung SYSMMU (IOMMU) driver
2011-03-04 9:01 ` [PATCH 3/7] ARM: Samsung: update/rewrite Samsung SYSMMU (IOMMU) driver Marek Szyprowski
@ 2011-03-04 16:04 ` Marek Szyprowski
2011-03-10 14:52 ` Arnd Bergmann
0 siblings, 1 reply; 29+ messages in thread
From: Marek Szyprowski @ 2011-03-04 16:04 UTC (permalink / raw)
To: linux-arm-kernel
From: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
This patch performs a complete rewrite of sysmmu driver for Samsung platform:
- the new version introduces an api to construct device private page
tables and enables to use device private address space mode
- simplified the resource management: no more single platform
device with 32 resources is needed, better fits into linux driver model,
each sysmmu instance has it's own resource definition
- added support for sysmmu clocks
- some other minor API chages required by upcoming videobuf2 allocator
Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
Hello,
I'm really sorry for breaking this patch in the previous mail. The
semi-colon is missing in the "EXPORT_SYMBOL_GPL(s5p_sysmmu_unmap_area)"
line. This is the fixed version.
Best regards
--
Marek Szyprowski
Samsung Poland R&D Center
---
arch/arm/mach-s5pv310/clock.c | 91 ++
arch/arm/mach-s5pv310/dev-sysmmu.c | 582 +++++++++----
arch/arm/mach-s5pv310/include/mach/irqs.h | 36 +-
arch/arm/mach-s5pv310/include/mach/regs-clock.h | 3 +
arch/arm/mach-s5pv310/include/mach/regs-sysmmu.h | 23 +-
arch/arm/mach-s5pv310/include/mach/sysmmu.h | 122 ---
arch/arm/plat-s5p/Kconfig | 17 +-
arch/arm/plat-s5p/include/plat/sysmmu.h | 127 +++
arch/arm/plat-s5p/sysmmu.c | 988 +++++++++++++++-------
arch/arm/plat-samsung/include/plat/devs.h | 2 +-
10 files changed, 1323 insertions(+), 668 deletions(-)
rewrite arch/arm/mach-s5pv310/dev-sysmmu.c (86%)
delete mode 100644 arch/arm/mach-s5pv310/include/mach/sysmmu.h
create mode 100644 arch/arm/plat-s5p/include/plat/sysmmu.h
rewrite arch/arm/plat-s5p/sysmmu.c (85%)
diff --git a/arch/arm/mach-s5pv310/clock.c b/arch/arm/mach-s5pv310/clock.c
index fc7c2f8..f142b8c 100644
--- a/arch/arm/mach-s5pv310/clock.c
+++ b/arch/arm/mach-s5pv310/clock.c
@@ -20,6 +20,7 @@
#include <plat/pll.h>
#include <plat/s5p-clock.h>
#include <plat/clock-clksrc.h>
+#include <plat/sysmmu.h>
#include <mach/map.h>
#include <mach/regs-clock.h>
@@ -116,6 +117,21 @@ static int s5pv310_clk_ip_perir_ctrl(struct clk *clk, int enable)
return s5p_gatectrl(S5P_CLKGATE_IP_PERIR, clk, enable);
}
+static int s5pv310_clk_ip_dmc_ctrl(struct clk *clk, int enable)
+{
+ return s5p_gatectrl(S5P_CLKGATE_IP_DMC, clk, enable);
+}
+
+static int s5pv310_clk_ip_mfc_ctrl(struct clk *clk, int enable)
+{
+ return s5p_gatectrl(S5P_CLKGATE_IP_MFC, clk, enable);
+}
+
+static int s5pv310_clk_ip_tv_ctrl(struct clk *clk, int enable)
+{
+ return s5p_gatectrl(S5P_CLKGATE_IP_TV, clk, enable);
+}
+
/* Core list of CMU_CPU side */
static struct clksrc_clk clk_mout_apll = {
@@ -422,6 +438,81 @@ static struct clk init_clocks_off[] = {
.enable = s5pv310_clk_ip_cam_ctrl,
.ctrlbit = (1 << 3),
}, {
+ .name = "sysmmu",
+ .id = S5P_SYSMMU_MFC_L,
+ .enable = s5pv310_clk_ip_mfc_ctrl,
+ .ctrlbit = ((15 << 1) | 1),
+ }, {
+ .name = "sysmmu",
+ .id = S5P_SYSMMU_MFC_R,
+ .enable = s5pv310_clk_ip_mfc_ctrl,
+ .ctrlbit = ((15 << 1) | 1),
+ }, {
+ .name = "sysmmu",
+ .id = S5P_SYSMMU_FIMC0,
+ .enable = s5pv310_clk_ip_cam_ctrl,
+ .ctrlbit = (1 << 7),
+ }, {
+ .name = "sysmmu",
+ .id = S5P_SYSMMU_FIMC1,
+ .enable = s5pv310_clk_ip_cam_ctrl,
+ .ctrlbit = (1 << 8),
+ } , {
+ .name = "sysmmu",
+ .id = S5P_SYSMMU_FIMC2,
+ .enable = s5pv310_clk_ip_cam_ctrl,
+ .ctrlbit = (1 << 9),
+ } , {
+ .name = "sysmmu",
+ .id = S5P_SYSMMU_FIMC3,
+ .enable = s5pv310_clk_ip_cam_ctrl,
+ .ctrlbit = (1 << 10),
+ } , {
+ .name = "sysmmu",
+ .id = S5P_SYSMMU_JPEG,
+ .enable = s5pv310_clk_ip_cam_ctrl,
+ .ctrlbit = (1 << 11),
+ } , {
+ .name = "sysmmu",
+ .id = S5P_SYSMMU_TV,
+ .enable = s5pv310_clk_ip_tv_ctrl,
+ .ctrlbit = (1 << 4),
+ } , {
+ .name = "sysmmu",
+ .id = S5P_SYSMMU_G2D,
+ .enable = s5pv310_clk_ip_image_ctrl,
+ .ctrlbit = (1 << 3),
+ } , {
+ .name = "sysmmu",
+ .id = S5P_SYSMMU_ROTATOR,
+ .enable = s5pv310_clk_ip_image_ctrl,
+ .ctrlbit = (1 << 4),
+ } , {
+ .name = "sysmmu",
+ .id = S5P_SYSMMU_MDMA,
+ .enable = s5pv310_clk_ip_image_ctrl,
+ .ctrlbit = (1 << 5),
+ } , {
+ .name = "sysmmu",
+ .id = S5P_SYSMMU_FIMD0,
+ .enable = s5pv310_clk_ip_lcd0_ctrl,
+ .ctrlbit = (1 << 4),
+ } , {
+ .name = "sysmmu",
+ .id = S5P_SYSMMU_FIMD1,
+ .enable = s5pv310_clk_ip_lcd1_ctrl,
+ .ctrlbit = (1 << 4),
+ } , {
+ .name = "sysmmu",
+ .id = S5P_SYSMMU_PCIe,
+ .enable = s5pv310_clk_ip_fsys_ctrl,
+ .ctrlbit = (1 << 18),
+ } , {
+ .name = "sysmmu",
+ .id = S5P_SYSMMU_SSS,
+ .enable = s5pv310_clk_ip_dmc_ctrl,
+ .ctrlbit = (1 << 12),
+ } , {
.name = "fimd",
.id = 0,
.enable = s5pv310_clk_ip_lcd0_ctrl,
diff --git a/arch/arm/mach-s5pv310/dev-sysmmu.c b/arch/arm/mach-s5pv310/dev-sysmmu.c
dissimilarity index 86%
index e1bb200..73c1541 100644
--- a/arch/arm/mach-s5pv310/dev-sysmmu.c
+++ b/arch/arm/mach-s5pv310/dev-sysmmu.c
@@ -1,187 +1,395 @@
-/* linux/arch/arm/mach-s5pv310/dev-sysmmu.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/platform_device.h>
-#include <linux/dma-mapping.h>
-
-#include <mach/map.h>
-#include <mach/irqs.h>
-
-static struct resource s5pv310_sysmmu_resource[] = {
- [0] = {
- .start = S5PV310_PA_SYSMMU_MDMA,
- .end = S5PV310_PA_SYSMMU_MDMA + SZ_64K - 1,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = IRQ_SYSMMU_MDMA0_0,
- .end = IRQ_SYSMMU_MDMA0_0,
- .flags = IORESOURCE_IRQ,
- },
- [2] = {
- .start = S5PV310_PA_SYSMMU_SSS,
- .end = S5PV310_PA_SYSMMU_SSS + SZ_64K - 1,
- .flags = IORESOURCE_MEM,
- },
- [3] = {
- .start = IRQ_SYSMMU_SSS_0,
- .end = IRQ_SYSMMU_SSS_0,
- .flags = IORESOURCE_IRQ,
- },
- [4] = {
- .start = S5PV310_PA_SYSMMU_FIMC0,
- .end = S5PV310_PA_SYSMMU_FIMC0 + SZ_64K - 1,
- .flags = IORESOURCE_MEM,
- },
- [5] = {
- .start = IRQ_SYSMMU_FIMC0_0,
- .end = IRQ_SYSMMU_FIMC0_0,
- .flags = IORESOURCE_IRQ,
- },
- [6] = {
- .start = S5PV310_PA_SYSMMU_FIMC1,
- .end = S5PV310_PA_SYSMMU_FIMC1 + SZ_64K - 1,
- .flags = IORESOURCE_MEM,
- },
- [7] = {
- .start = IRQ_SYSMMU_FIMC1_0,
- .end = IRQ_SYSMMU_FIMC1_0,
- .flags = IORESOURCE_IRQ,
- },
- [8] = {
- .start = S5PV310_PA_SYSMMU_FIMC2,
- .end = S5PV310_PA_SYSMMU_FIMC2 + SZ_64K - 1,
- .flags = IORESOURCE_MEM,
- },
- [9] = {
- .start = IRQ_SYSMMU_FIMC2_0,
- .end = IRQ_SYSMMU_FIMC2_0,
- .flags = IORESOURCE_IRQ,
- },
- [10] = {
- .start = S5PV310_PA_SYSMMU_FIMC3,
- .end = S5PV310_PA_SYSMMU_FIMC3 + SZ_64K - 1,
- .flags = IORESOURCE_MEM,
- },
- [11] = {
- .start = IRQ_SYSMMU_FIMC3_0,
- .end = IRQ_SYSMMU_FIMC3_0,
- .flags = IORESOURCE_IRQ,
- },
- [12] = {
- .start = S5PV310_PA_SYSMMU_JPEG,
- .end = S5PV310_PA_SYSMMU_JPEG + SZ_64K - 1,
- .flags = IORESOURCE_MEM,
- },
- [13] = {
- .start = IRQ_SYSMMU_JPEG_0,
- .end = IRQ_SYSMMU_JPEG_0,
- .flags = IORESOURCE_IRQ,
- },
- [14] = {
- .start = S5PV310_PA_SYSMMU_FIMD0,
- .end = S5PV310_PA_SYSMMU_FIMD0 + SZ_64K - 1,
- .flags = IORESOURCE_MEM,
- },
- [15] = {
- .start = IRQ_SYSMMU_LCD0_M0_0,
- .end = IRQ_SYSMMU_LCD0_M0_0,
- .flags = IORESOURCE_IRQ,
- },
- [16] = {
- .start = S5PV310_PA_SYSMMU_FIMD1,
- .end = S5PV310_PA_SYSMMU_FIMD1 + SZ_64K - 1,
- .flags = IORESOURCE_MEM,
- },
- [17] = {
- .start = IRQ_SYSMMU_LCD1_M1_0,
- .end = IRQ_SYSMMU_LCD1_M1_0,
- .flags = IORESOURCE_IRQ,
- },
- [18] = {
- .start = S5PV310_PA_SYSMMU_PCIe,
- .end = S5PV310_PA_SYSMMU_PCIe + SZ_64K - 1,
- .flags = IORESOURCE_MEM,
- },
- [19] = {
- .start = IRQ_SYSMMU_PCIE_0,
- .end = IRQ_SYSMMU_PCIE_0,
- .flags = IORESOURCE_IRQ,
- },
- [20] = {
- .start = S5PV310_PA_SYSMMU_G2D,
- .end = S5PV310_PA_SYSMMU_G2D + SZ_64K - 1,
- .flags = IORESOURCE_MEM,
- },
- [21] = {
- .start = IRQ_SYSMMU_2D_0,
- .end = IRQ_SYSMMU_2D_0,
- .flags = IORESOURCE_IRQ,
- },
- [22] = {
- .start = S5PV310_PA_SYSMMU_ROTATOR,
- .end = S5PV310_PA_SYSMMU_ROTATOR + SZ_64K - 1,
- .flags = IORESOURCE_MEM,
- },
- [23] = {
- .start = IRQ_SYSMMU_ROTATOR_0,
- .end = IRQ_SYSMMU_ROTATOR_0,
- .flags = IORESOURCE_IRQ,
- },
- [24] = {
- .start = S5PV310_PA_SYSMMU_MDMA2,
- .end = S5PV310_PA_SYSMMU_MDMA2 + SZ_64K - 1,
- .flags = IORESOURCE_MEM,
- },
- [25] = {
- .start = IRQ_SYSMMU_MDMA1_0,
- .end = IRQ_SYSMMU_MDMA1_0,
- .flags = IORESOURCE_IRQ,
- },
- [26] = {
- .start = S5PV310_PA_SYSMMU_TV,
- .end = S5PV310_PA_SYSMMU_TV + SZ_64K - 1,
- .flags = IORESOURCE_MEM,
- },
- [27] = {
- .start = IRQ_SYSMMU_TV_M0_0,
- .end = IRQ_SYSMMU_TV_M0_0,
- .flags = IORESOURCE_IRQ,
- },
- [28] = {
- .start = S5PV310_PA_SYSMMU_MFC_L,
- .end = S5PV310_PA_SYSMMU_MFC_L + SZ_64K - 1,
- .flags = IORESOURCE_MEM,
- },
- [29] = {
- .start = IRQ_SYSMMU_MFC_M0_0,
- .end = IRQ_SYSMMU_MFC_M0_0,
- .flags = IORESOURCE_IRQ,
- },
- [30] = {
- .start = S5PV310_PA_SYSMMU_MFC_R,
- .end = S5PV310_PA_SYSMMU_MFC_R + SZ_64K - 1,
- .flags = IORESOURCE_MEM,
- },
- [31] = {
- .start = IRQ_SYSMMU_MFC_M1_0,
- .end = IRQ_SYSMMU_MFC_M1_0,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-struct platform_device s5pv310_device_sysmmu = {
- .name = "s5p-sysmmu",
- .id = 32,
- .num_resources = ARRAY_SIZE(s5pv310_sysmmu_resource),
- .resource = s5pv310_sysmmu_resource,
-};
-
-EXPORT_SYMBOL(s5pv310_device_sysmmu);
+/* linux/arch/arm/mach-s5pv310/dev-sysmmu.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+
+#include <mach/map.h>
+#include <mach/irqs.h>
+
+#include <plat/devs.h>
+#include <plat/cpu.h>
+#include <plat/sysmmu.h>
+
+static struct resource s5p_sysmmu_resource[][2] = {
+ [S5P_SYSMMU_MDMA] = {
+ [0] = {
+ .start = S5PV310_PA_SYSMMU_MDMA,
+ .end = S5PV310_PA_SYSMMU_MDMA + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_SYSMMU_MDMA0,
+ .end = IRQ_SYSMMU_MDMA0,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ [S5P_SYSMMU_SSS] = {
+ [0] = {
+ .start = S5PV310_PA_SYSMMU_SSS,
+ .end = S5PV310_PA_SYSMMU_SSS + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_SYSMMU_SSS,
+ .end = IRQ_SYSMMU_SSS,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ [S5P_SYSMMU_FIMC0] = {
+ [0] = {
+ .start = S5PV310_PA_SYSMMU_FIMC0,
+ .end = S5PV310_PA_SYSMMU_FIMC0 + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_SYSMMU_FIMC0,
+ .end = IRQ_SYSMMU_FIMC0,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ [S5P_SYSMMU_FIMC1] = {
+ [0] = {
+ .start = S5PV310_PA_SYSMMU_FIMC1,
+ .end = S5PV310_PA_SYSMMU_FIMC1 + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_SYSMMU_FIMC1,
+ .end = IRQ_SYSMMU_FIMC1,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ [S5P_SYSMMU_FIMC2] = {
+ [0] = {
+ .start = S5PV310_PA_SYSMMU_FIMC2,
+ .end = S5PV310_PA_SYSMMU_FIMC2 + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_SYSMMU_FIMC2,
+ .end = IRQ_SYSMMU_FIMC2,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ [S5P_SYSMMU_FIMC3] = {
+ [0] = {
+ .start = S5PV310_PA_SYSMMU_FIMC3,
+ .end = S5PV310_PA_SYSMMU_FIMC3 + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_SYSMMU_FIMC3,
+ .end = IRQ_SYSMMU_FIMC3,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ [S5P_SYSMMU_JPEG] = {
+ [0] = {
+ .start = S5PV310_PA_SYSMMU_JPEG,
+ .end = S5PV310_PA_SYSMMU_JPEG + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_SYSMMU_JPEG,
+ .end = IRQ_SYSMMU_JPEG,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ [S5P_SYSMMU_FIMD0] = {
+ [0] = {
+ .start = S5PV310_PA_SYSMMU_FIMD0,
+ .end = S5PV310_PA_SYSMMU_FIMD0 + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_SYSMMU_FIMD0,
+ .end = IRQ_SYSMMU_FIMD0,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ [S5P_SYSMMU_FIMD1] = {
+ [0] = {
+ .start = S5PV310_PA_SYSMMU_FIMD1,
+ .end = S5PV310_PA_SYSMMU_FIMD1 + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_SYSMMU_FIMD1,
+ .end = IRQ_SYSMMU_FIMD1,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ [S5P_SYSMMU_PCIe] = {
+ [0] = {
+ .start = S5PV310_PA_SYSMMU_PCIe,
+ .end = S5PV310_PA_SYSMMU_PCIe + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_SYSMMU_PCIE,
+ .end = IRQ_SYSMMU_PCIE,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ [S5P_SYSMMU_G2D] = {
+ [0] = {
+ .start = S5PV310_PA_SYSMMU_G2D,
+ .end = S5PV310_PA_SYSMMU_G2D + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_SYSMMU_2D,
+ .end = IRQ_SYSMMU_2D,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ [S5P_SYSMMU_ROTATOR] = {
+ [0] = {
+ .start = S5PV310_PA_SYSMMU_ROTATOR,
+ .end = S5PV310_PA_SYSMMU_ROTATOR + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_SYSMMU_ROTATOR,
+ .end = IRQ_SYSMMU_ROTATOR,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ [S5P_SYSMMU_MDMA2] = {
+ [0] = {
+ .start = S5PV310_PA_SYSMMU_MDMA2,
+ .end = S5PV310_PA_SYSMMU_MDMA2 + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_SYSMMU_MDMA1,
+ .end = IRQ_SYSMMU_MDMA1,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ [S5P_SYSMMU_TV] = {
+ [0] = {
+ .start = S5PV310_PA_SYSMMU_TV,
+ .end = S5PV310_PA_SYSMMU_TV + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_SYSMMU_TV,
+ .end = IRQ_SYSMMU_TV,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ [S5P_SYSMMU_MFC_L] = {
+ [0] = {
+ .start = S5PV310_PA_SYSMMU_MFC_L,
+ .end = S5PV310_PA_SYSMMU_MFC_L + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_SYSMMU_MFC_L,
+ .end = IRQ_SYSMMU_MFC_L,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+ [S5P_SYSMMU_MFC_R] = {
+ [0] = {
+ .start = S5PV310_PA_SYSMMU_MFC_R,
+ .end = S5PV310_PA_SYSMMU_MFC_R + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_SYSMMU_MFC_R,
+ .end = IRQ_SYSMMU_MFC_R,
+ .flags = IORESOURCE_IRQ,
+ },
+ },
+};
+
+static u64 s5p_sysmmu_dma_mask = DMA_BIT_MASK(32);
+
+struct platform_device s5pv310_device_sysmmu[] = {
+ [S5P_SYSMMU_MDMA] = {
+ .name = "s5p-sysmmu",
+ .id = S5P_SYSMMU_MDMA,
+ .num_resources = ARRAY_SIZE(
+ s5p_sysmmu_resource[S5P_SYSMMU_MDMA]),
+ .resource = s5p_sysmmu_resource[S5P_SYSMMU_MDMA],
+ .dev = {
+ .dma_mask = &s5p_sysmmu_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ },
+ [S5P_SYSMMU_SSS] = {
+ .name = "s5p-sysmmu",
+ .id = S5P_SYSMMU_SSS,
+ .num_resources = ARRAY_SIZE(
+ s5p_sysmmu_resource[S5P_SYSMMU_SSS]),
+ .resource = s5p_sysmmu_resource[S5P_SYSMMU_SSS],
+ .dev = {
+ .dma_mask = &s5p_sysmmu_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ },
+ [S5P_SYSMMU_FIMC0] = {
+ .name = "s5p-sysmmu",
+ .id = S5P_SYSMMU_FIMC0,
+ .num_resources = ARRAY_SIZE(
+ s5p_sysmmu_resource[S5P_SYSMMU_FIMC0]),
+ .resource = s5p_sysmmu_resource[S5P_SYSMMU_FIMC0],
+ .dev = {
+ .dma_mask = &s5p_sysmmu_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ },
+ [S5P_SYSMMU_FIMC1] = {
+ .name = "s5p-sysmmu",
+ .id = S5P_SYSMMU_FIMC1,
+ .num_resources = ARRAY_SIZE(
+ s5p_sysmmu_resource[S5P_SYSMMU_FIMC1]),
+ .resource = s5p_sysmmu_resource[S5P_SYSMMU_FIMC1],
+ .dev = {
+ .dma_mask = &s5p_sysmmu_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ },
+ [S5P_SYSMMU_FIMC2] = {
+ .name = "s5p-sysmmu",
+ .id = S5P_SYSMMU_FIMC2,
+ .num_resources = ARRAY_SIZE(
+ s5p_sysmmu_resource[S5P_SYSMMU_FIMC2]),
+ .resource = s5p_sysmmu_resource[S5P_SYSMMU_FIMC2],
+ .dev = {
+ .dma_mask = &s5p_sysmmu_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ },
+ [S5P_SYSMMU_FIMC3] = {
+ .name = "s5p-sysmmu",
+ .id = S5P_SYSMMU_FIMC3,
+ .num_resources = ARRAY_SIZE(
+ s5p_sysmmu_resource[S5P_SYSMMU_FIMC3]),
+ .resource = s5p_sysmmu_resource[S5P_SYSMMU_FIMC3],
+ .dev = {
+ .dma_mask = &s5p_sysmmu_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ },
+ [S5P_SYSMMU_JPEG] = {
+ .name = "s5p-sysmmu",
+ .id = S5P_SYSMMU_JPEG,
+ .num_resources = ARRAY_SIZE(
+ s5p_sysmmu_resource[S5P_SYSMMU_JPEG]),
+ .resource = s5p_sysmmu_resource[S5P_SYSMMU_JPEG],
+ .dev = {
+ .dma_mask = &s5p_sysmmu_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ },
+ [S5P_SYSMMU_FIMD0] = {
+ .name = "s5p-sysmmu",
+ .id = S5P_SYSMMU_FIMD0,
+ .num_resources = ARRAY_SIZE(
+ s5p_sysmmu_resource[S5P_SYSMMU_FIMD0]),
+ .resource = s5p_sysmmu_resource[S5P_SYSMMU_FIMD0],
+ .dev = {
+ .dma_mask = &s5p_sysmmu_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ },
+ [S5P_SYSMMU_FIMD1] = {
+ .name = "s5p-sysmmu",
+ .id = S5P_SYSMMU_FIMD1,
+ .num_resources = ARRAY_SIZE(
+ s5p_sysmmu_resource[S5P_SYSMMU_FIMD1]),
+ .resource = s5p_sysmmu_resource[S5P_SYSMMU_FIMD1],
+ .dev = {
+ .dma_mask = &s5p_sysmmu_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ },
+ [S5P_SYSMMU_PCIe] = {
+ .name = "s5p-sysmmu",
+ .id = S5P_SYSMMU_PCIe,
+ .num_resources = ARRAY_SIZE(
+ s5p_sysmmu_resource[S5P_SYSMMU_PCIe]),
+ .resource = s5p_sysmmu_resource[S5P_SYSMMU_PCIe],
+ .dev = {
+ .dma_mask = &s5p_sysmmu_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ },
+ [S5P_SYSMMU_G2D] = {
+ .name = "s5p-sysmmu",
+ .id = S5P_SYSMMU_G2D,
+ .num_resources = ARRAY_SIZE(
+ s5p_sysmmu_resource[S5P_SYSMMU_G2D]),
+ .resource = s5p_sysmmu_resource[S5P_SYSMMU_G2D],
+ .dev = {
+ .dma_mask = &s5p_sysmmu_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ },
+ [S5P_SYSMMU_ROTATOR] = {
+ .name = "s5p-sysmmu",
+ .id = S5P_SYSMMU_ROTATOR,
+ .num_resources = ARRAY_SIZE(
+ s5p_sysmmu_resource[S5P_SYSMMU_ROTATOR]),
+ .resource = s5p_sysmmu_resource[S5P_SYSMMU_ROTATOR],
+ .dev = {
+ .dma_mask = &s5p_sysmmu_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ },
+ [S5P_SYSMMU_MDMA2] = {
+ .name = "s5p-sysmmu",
+ .id = S5P_SYSMMU_MDMA2,
+ .num_resources = ARRAY_SIZE(
+ s5p_sysmmu_resource[S5P_SYSMMU_MDMA2]),
+ .resource = s5p_sysmmu_resource[S5P_SYSMMU_MDMA2],
+ .dev = {
+ .dma_mask = &s5p_sysmmu_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ },
+ [S5P_SYSMMU_TV] = {
+ .name = "s5p-sysmmu",
+ .id = S5P_SYSMMU_TV,
+ .num_resources = ARRAY_SIZE(
+ s5p_sysmmu_resource[S5P_SYSMMU_TV]),
+ .resource = s5p_sysmmu_resource[S5P_SYSMMU_TV],
+ .dev = {
+ .dma_mask = &s5p_sysmmu_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ },
+ [S5P_SYSMMU_MFC_L] = {
+ .name = "s5p-sysmmu",
+ .id = S5P_SYSMMU_MFC_L,
+ .num_resources = ARRAY_SIZE(
+ s5p_sysmmu_resource[S5P_SYSMMU_MFC_L]),
+ .resource = s5p_sysmmu_resource[S5P_SYSMMU_MFC_L],
+ .dev = {
+ .dma_mask = &s5p_sysmmu_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ },
+ [S5P_SYSMMU_MFC_R] = {
+ .name = "s5p-sysmmu",
+ .id = S5P_SYSMMU_MFC_R,
+ .num_resources = ARRAY_SIZE(
+ s5p_sysmmu_resource[S5P_SYSMMU_MFC_R]),
+ .resource = s5p_sysmmu_resource[S5P_SYSMMU_MFC_R],
+ .dev = {
+ .dma_mask = &s5p_sysmmu_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ },
+};
diff --git a/arch/arm/mach-s5pv310/include/mach/irqs.h b/arch/arm/mach-s5pv310/include/mach/irqs.h
index 0e99968..f6b99c6 100644
--- a/arch/arm/mach-s5pv310/include/mach/irqs.h
+++ b/arch/arm/mach-s5pv310/include/mach/irqs.h
@@ -55,23 +55,24 @@
#define COMBINER_GROUP(x) ((x) * MAX_IRQ_IN_COMBINER + IRQ_SPI(64))
#define COMBINER_IRQ(x, y) (COMBINER_GROUP(x) + y)
-#define IRQ_SYSMMU_MDMA0_0 COMBINER_IRQ(4, 0)
-#define IRQ_SYSMMU_SSS_0 COMBINER_IRQ(4, 1)
-#define IRQ_SYSMMU_FIMC0_0 COMBINER_IRQ(4, 2)
-#define IRQ_SYSMMU_FIMC1_0 COMBINER_IRQ(4, 3)
-#define IRQ_SYSMMU_FIMC2_0 COMBINER_IRQ(4, 4)
-#define IRQ_SYSMMU_FIMC3_0 COMBINER_IRQ(4, 5)
-#define IRQ_SYSMMU_JPEG_0 COMBINER_IRQ(4, 6)
-#define IRQ_SYSMMU_2D_0 COMBINER_IRQ(4, 7)
-
-#define IRQ_SYSMMU_ROTATOR_0 COMBINER_IRQ(5, 0)
-#define IRQ_SYSMMU_MDMA1_0 COMBINER_IRQ(5, 1)
-#define IRQ_SYSMMU_LCD0_M0_0 COMBINER_IRQ(5, 2)
-#define IRQ_SYSMMU_LCD1_M1_0 COMBINER_IRQ(5, 3)
-#define IRQ_SYSMMU_TV_M0_0 COMBINER_IRQ(5, 4)
-#define IRQ_SYSMMU_MFC_M0_0 COMBINER_IRQ(5, 5)
-#define IRQ_SYSMMU_MFC_M1_0 COMBINER_IRQ(5, 6)
-#define IRQ_SYSMMU_PCIE_0 COMBINER_IRQ(5, 7)
+#define IRQ_SYSMMU_MDMA0 COMBINER_IRQ(4, 0)
+#define IRQ_SYSMMU_SSS COMBINER_IRQ(4, 1)
+#define IRQ_SYSMMU_FIMC0 COMBINER_IRQ(4, 2)
+#define IRQ_SYSMMU_FIMC1 COMBINER_IRQ(4, 3)
+#define IRQ_SYSMMU_FIMC2 COMBINER_IRQ(4, 4)
+#define IRQ_SYSMMU_FIMC3 COMBINER_IRQ(4, 5)
+#define IRQ_SYSMMU_JPEG COMBINER_IRQ(4, 6)
+#define IRQ_SYSMMU_2D COMBINER_IRQ(4, 7)
+
+#define IRQ_SYSMMU_ROTATOR COMBINER_IRQ(5, 0)
+#define IRQ_SYSMMU_MDMA1 COMBINER_IRQ(5, 1)
+#define IRQ_SYSMMU_FIMD0 COMBINER_IRQ(5, 2)
+#define IRQ_SYSMMU_FIMD1 COMBINER_IRQ(5, 3)
+#define IRQ_SYSMMU_TV COMBINER_IRQ(5, 4)
+#define IRQ_SYSMMU_MFC_L COMBINER_IRQ(5, 5)
+#define IRQ_SYSMMU_MFC_R COMBINER_IRQ(5, 6)
+#define IRQ_SYSMMU_PCIE COMBINER_IRQ(5, 7)
+
#define IRQ_PDMA0 COMBINER_IRQ(21, 0)
#define IRQ_PDMA1 COMBINER_IRQ(21, 1)
@@ -147,4 +148,5 @@
#define NR_IRQS (S5P_IRQ_EINT_BASE + 32)
+
#endif /* __ASM_ARCH_IRQS_H */
diff --git a/arch/arm/mach-s5pv310/include/mach/regs-clock.h b/arch/arm/mach-s5pv310/include/mach/regs-clock.h
index 341571a..9ef5f0c 100644
--- a/arch/arm/mach-s5pv310/include/mach/regs-clock.h
+++ b/arch/arm/mach-s5pv310/include/mach/regs-clock.h
@@ -67,6 +67,8 @@
#define S5P_CLKDIV_STAT_TOP S5P_CLKREG(0x0C610)
#define S5P_CLKGATE_IP_CAM S5P_CLKREG(0x0C920)
+#define S5P_CLKGATE_IP_MFC S5P_CLKREG(0x0C928)
+#define S5P_CLKGATE_IP_TV S5P_CLKREG(0x0C924)
#define S5P_CLKGATE_IP_IMAGE S5P_CLKREG(0x0C930)
#define S5P_CLKGATE_IP_LCD0 S5P_CLKREG(0x0C934)
#define S5P_CLKGATE_IP_LCD1 S5P_CLKREG(0x0C938)
@@ -78,6 +80,7 @@
#define S5P_CLKSRC_DMC S5P_CLKREG(0x10200)
#define S5P_CLKDIV_DMC0 S5P_CLKREG(0x10500)
#define S5P_CLKDIV_STAT_DMC0 S5P_CLKREG(0x10600)
+#define S5P_CLKGATE_IP_DMC S5P_CLKREG(0x10900)
#define S5P_APLL_LOCK S5P_CLKREG(0x14000)
#define S5P_MPLL_LOCK S5P_CLKREG(0x14004)
diff --git a/arch/arm/mach-s5pv310/include/mach/regs-sysmmu.h b/arch/arm/mach-s5pv310/include/mach/regs-sysmmu.h
index 0b28e81..dd2a954 100644
--- a/arch/arm/mach-s5pv310/include/mach/regs-sysmmu.h
+++ b/arch/arm/mach-s5pv310/include/mach/regs-sysmmu.h
@@ -13,12 +13,21 @@
#ifndef __ASM_ARCH_REGS_SYSMMU_H
#define __ASM_ARCH_REGS_SYSMMU_H __FILE__
-#define S5P_MMU_CTRL 0x000
-#define S5P_MMU_CFG 0x004
-#define S5P_MMU_STATUS 0x008
-#define S5P_MMU_FLUSH 0x00C
-#define S5P_PT_BASE_ADDR 0x014
-#define S5P_INT_STATUS 0x018
-#define S5P_PAGE_FAULT_ADDR 0x024
+#define S5P_MMU_CTRL (0x000)
+#define S5P_MMU_CFG (0x004)
+#define S5P_MMU_STATUS (0x008)
+#define S5P_MMU_FLUSH (0x00C)
+#define S5P_MMU_FLUSH_ENTRY (0x010)
+#define S5P_PT_BASE_ADDR (0x014)
+#define S5P_INT_STATUS (0x018)
+#define S5P_INT_CLEAR (0x01C)
+#define S5P_INT_MASK (0x020)
+#define S5P_PAGE_FAULT_ADDR (0x024)
+#define S5P_AW_FAULT_ADDR (0x028)
+#define S5P_AR_FAULT_ADDR (0x02C)
+#define S5P_DEFAULT_SLAVE_ADDR (0x030)
+#define S5P_MMU_VERSION (0x034)
+#define S5P_TLB_READ (0x038)
+#define S5P_TLB_DATA (0x03C)
#endif /* __ASM_ARCH_REGS_SYSMMU_H */
diff --git a/arch/arm/mach-s5pv310/include/mach/sysmmu.h b/arch/arm/mach-s5pv310/include/mach/sysmmu.h
deleted file mode 100644
index 598fc5c..0000000
--- a/arch/arm/mach-s5pv310/include/mach/sysmmu.h
+++ /dev/null
@@ -1,122 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/include/mach/sysmmu.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com/
- *
- * Samsung sysmmu driver for S5PV310
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARM_ARCH_SYSMMU_H
-#define __ASM_ARM_ARCH_SYSMMU_H __FILE__
-
-#define S5PV310_SYSMMU_TOTAL_IPNUM 16
-#define S5P_SYSMMU_TOTAL_IPNUM S5PV310_SYSMMU_TOTAL_IPNUM
-
-enum s5pv310_sysmmu_ips {
- SYSMMU_MDMA,
- SYSMMU_SSS,
- SYSMMU_FIMC0,
- SYSMMU_FIMC1,
- SYSMMU_FIMC2,
- SYSMMU_FIMC3,
- SYSMMU_JPEG,
- SYSMMU_FIMD0,
- SYSMMU_FIMD1,
- SYSMMU_PCIe,
- SYSMMU_G2D,
- SYSMMU_ROTATOR,
- SYSMMU_MDMA2,
- SYSMMU_TV,
- SYSMMU_MFC_L,
- SYSMMU_MFC_R,
-};
-
-static char *sysmmu_ips_name[S5PV310_SYSMMU_TOTAL_IPNUM] = {
- "SYSMMU_MDMA" ,
- "SYSMMU_SSS" ,
- "SYSMMU_FIMC0" ,
- "SYSMMU_FIMC1" ,
- "SYSMMU_FIMC2" ,
- "SYSMMU_FIMC3" ,
- "SYSMMU_JPEG" ,
- "SYSMMU_FIMD0" ,
- "SYSMMU_FIMD1" ,
- "SYSMMU_PCIe" ,
- "SYSMMU_G2D" ,
- "SYSMMU_ROTATOR",
- "SYSMMU_MDMA2" ,
- "SYSMMU_TV" ,
- "SYSMMU_MFC_L" ,
- "SYSMMU_MFC_R" ,
-};
-
-typedef enum s5pv310_sysmmu_ips sysmmu_ips;
-
-struct sysmmu_tt_info {
- unsigned long *pgd;
- unsigned long pgd_paddr;
- unsigned long *pte;
-};
-
-struct sysmmu_controller {
- const char *name;
-
- /* channels registers */
- void __iomem *regs;
-
- /* channel irq */
- unsigned int irq;
-
- sysmmu_ips ips;
-
- /* Translation Table Info. */
- struct sysmmu_tt_info *tt_info;
-
- struct resource *mem;
- struct device *dev;
-
- /* SysMMU controller enable - true : enable */
- bool enable;
-};
-
-/**
- * s5p_sysmmu_enable() - enable system mmu of ip
- * @ips: The ip connected system mmu.
- *
- * This function enable system mmu to transfer address
- * from virtual address to physical address
- */
-int s5p_sysmmu_enable(sysmmu_ips ips);
-
-/**
- * s5p_sysmmu_disable() - disable sysmmu mmu of ip
- * @ips: The ip connected system mmu.
- *
- * This function disable system mmu to transfer address
- * from virtual address to physical address
- */
-int s5p_sysmmu_disable(sysmmu_ips ips);
-
-/**
- * s5p_sysmmu_set_tablebase_pgd() - set page table base address to refer page table
- * @ips: The ip connected system mmu.
- * @pgd: The page table base address.
- *
- * This function set page table base address
- * When system mmu transfer address from virtaul address to physical address,
- * system mmu refer address information from page table
- */
-int s5p_sysmmu_set_tablebase_pgd(sysmmu_ips ips, unsigned long pgd);
-
-/**
- * s5p_sysmmu_tlb_invalidate() - flush all TLB entry in system mmu
- * @ips: The ip connected system mmu.
- *
- * This function flush all TLB entry in system mmu
- */
-int s5p_sysmmu_tlb_invalidate(sysmmu_ips ips);
-#endif /* __ASM_ARM_ARCH_SYSMMU_H */
diff --git a/arch/arm/plat-s5p/Kconfig b/arch/arm/plat-s5p/Kconfig
index 0db2a7a..4166964 100644
--- a/arch/arm/plat-s5p/Kconfig
+++ b/arch/arm/plat-s5p/Kconfig
@@ -37,14 +37,6 @@ config S5P_GPIO_INT
help
Common code for the GPIO interrupts (other than external interrupts.)
-comment "System MMU"
-
-config S5P_SYSTEM_MMU
- bool "S5P SYSTEM MMU"
- depends on ARCH_S5PV310
- help
- Say Y here if you want to enable System MMU
-
config S5P_DEV_FIMC0
bool
help
@@ -79,3 +71,12 @@ config S5P_DEV_CSIS1
bool
help
Compile in platform device definitions for MIPI-CSIS channel 1
+
+comment "System MMU"
+
+config S5P_SYSTEM_MMU
+ bool "S5P SYSTEM MMU"
+ depends on ARCH_S5PV310
+ help
+ Say Y here if you want to enable System MMU
+
diff --git a/arch/arm/plat-s5p/include/plat/sysmmu.h b/arch/arm/plat-s5p/include/plat/sysmmu.h
new file mode 100644
index 0000000..9051af4
--- /dev/null
+++ b/arch/arm/plat-s5p/include/plat/sysmmu.h
@@ -0,0 +1,127 @@
+/*
+ * sysmmu.h
+ *
+ * Copyright (C) 2011 Samsung Electronics
+ *
+ * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation.
+ */
+#ifndef __S5P_SYSMMU_H__
+#define __S5P_SYSMMU_H__
+
+struct device;
+
+/**
+ * enum s5p_sysmmu_cmd - sysmmu control commands
+ * @S5P_SYSMMU_ENABLE_SHARED: enable sysmmu, share page tables with ARM CPU
+ * @S5P_SYSMMU_ENABLE_PRIVATE: enable sysmmu, use private page tables
+ * @S5P_SYSMMU_DISABLE: disable sysmmu
+ * @S5P_SYSMMU_TLB_INVALIDATE: invalidate sysmmu TLB contents
+ */
+enum s5p_sysmmu_cmd {
+ S5P_SYSMMU_ENABLE_SHARED,
+ S5P_SYSMMU_ENABLE_PRIVATE,
+ S5P_SYSMMU_DISABLE,
+ S5P_SYSMMU_TLB_INVALIDATE,
+};
+
+/**
+ * enum s5p_sysmmu_ip - integrated peripherals identifiers
+ * @S5P_SYSMMU_MDMA: MDMA
+ * @S5P_SYSMMU_SSS: SSS
+ * @S5P_SYSMMU_FIMC0: FIMC0
+ * @S5P_SYSMMU_FIMC1: FIMC1
+ * @S5P_SYSMMU_FIMC2: FIMC2
+ * @S5P_SYSMMU_FIMC3: FIMC3
+ * @S5P_SYSMMU_JPEG: JPEG
+ * @S5P_SYSMMU_FIMD0: FIMD0
+ * @S5P_SYSMMU_FIMD1: FIMD1
+ * @S5P_SYSMMU_PCIe: PCIe
+ * @S5P_SYSMMU_G2D: G2D
+ * @S5P_SYSMMU_ROTATOR: ROTATOR
+ * @S5P_SYSMMU_MDMA2: MDMA2
+ * @S5P_SYSMMU_TV: TV
+ * @S5P_SYSMMU_MFC_L: MFC_L
+ * @S5P_SYSMMU_MFC_R: MFC_R
+ */
+enum s5p_sysmmu_ip {
+ S5P_SYSMMU_MDMA,
+ S5P_SYSMMU_SSS,
+ S5P_SYSMMU_FIMC0,
+ S5P_SYSMMU_FIMC1,
+ S5P_SYSMMU_FIMC2,
+ S5P_SYSMMU_FIMC3,
+ S5P_SYSMMU_JPEG,
+ S5P_SYSMMU_FIMD0,
+ S5P_SYSMMU_FIMD1,
+ S5P_SYSMMU_PCIe,
+ S5P_SYSMMU_G2D,
+ S5P_SYSMMU_ROTATOR,
+ S5P_SYSMMU_MDMA2,
+ S5P_SYSMMU_TV,
+ S5P_SYSMMU_MFC_L,
+ S5P_SYSMMU_MFC_R,
+};
+
+/**
+ * s5p_sysmmu_get() - get sysmmu handle for a device
+ * @dev: device which needs to use its sysmmu
+ * @ip: integrated peripheral identifier of the device
+ */
+void *s5p_sysmmu_get(struct device *dev, enum s5p_sysmmu_ip ip);
+
+/**
+ * s5p_sysmmu_put() - release sysmmu handle for a device
+ * @dev_id: sysmmu handle obtained from s5p_sysmmu_get()
+ */
+void s5p_sysmmu_put(void *dev_id);
+
+/**
+ * s5p_sysmmu_control() - control a sysmmu
+ * @dev_id: sysmmu handle obtained from s5p_sysmmu_get()
+ * @cmd: command to perform
+ */
+int s5p_sysmmu_control(void *dev_id, enum s5p_sysmmu_cmd cmd);
+
+/**
+ * s5p_sysmmu_map_area() - map an area of device's virtual memory,
+ underlying memory is described by struct pages
+ * @dev_id: sysmmu handle obtained from s5p_sysmmu_get()
+ * @varea_start: beginning virtual address of the mapped area,
+ * must be page aligned
+ * @num_pages: number of pages to map starting from varea_start
+ * @pages: an array of struct page pointers representing
+ * the physical pages which will be mapped
+ */
+int s5p_sysmmu_map_area(void *dev_id, unsigned long varea_start,
+ unsigned long num_pages, struct page **pages);
+
+/**
+ * s5p_sysmmu_map_phys_area() - map an area of device's virtual memory,
+ * underlying memory is a physically contiguous block
+ * @dev_id: sysmmu handle obtained from s5p_sysmmu_get()
+ * @varea_start: beginning virtual address of the mapped area,
+ * must be page aligned
+ * @phys_area_start: beginning physical adddress of the underlying memory
+ * @num_pages: number of pages to map starting from phys_area_start
+ */
+int s5p_sysmmu_map_phys_area(void *dev_id, unsigned long varea_start,
+ unsigned long phys_area_start,
+ unsigned long num_pages);
+
+/**
+ * s5p_sysmmu_unmap_area() - unmap an area of device's virtual memory
+ * @dev_id: sysmmu handle obtained from s5p_sysmmu_get()
+ * @varea_start: beginning virtual address of the mapped area,
+ * must be page aligned and correspond to the address
+ * used while mapping
+ * @num_pages: number of pages to unmap starting from phys_area_start,
+ * must correspond to the number used while mapping
+ */
+void s5p_sysmmu_unmap_area(void *dev_id, unsigned long varea_start,
+ unsigned long num_pages);
+
+#endif /* __S5P_SYSMMU_H__ */
diff --git a/arch/arm/plat-s5p/sysmmu.c b/arch/arm/plat-s5p/sysmmu.c
dissimilarity index 85%
index ffe8a48..45adbf4 100644
--- a/arch/arm/plat-s5p/sysmmu.c
+++ b/arch/arm/plat-s5p/sysmmu.c
@@ -1,326 +1,662 @@
-/* linux/arch/arm/plat-s5p/sysmmu.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/io.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-
-#include <mach/map.h>
-#include <mach/regs-sysmmu.h>
-#include <mach/sysmmu.h>
-
-struct sysmmu_controller s5p_sysmmu_cntlrs[S5P_SYSMMU_TOTAL_IPNUM];
-
-void s5p_sysmmu_register(struct sysmmu_controller *sysmmuconp)
-{
- unsigned int reg_mmu_ctrl;
- unsigned int reg_mmu_status;
- unsigned int reg_pt_base_addr;
- unsigned int reg_int_status;
- unsigned int reg_page_ft_addr;
-
- reg_int_status = __raw_readl(sysmmuconp->regs + S5P_INT_STATUS);
- reg_mmu_ctrl = __raw_readl(sysmmuconp->regs + S5P_MMU_CTRL);
- reg_mmu_status = __raw_readl(sysmmuconp->regs + S5P_MMU_STATUS);
- reg_pt_base_addr = __raw_readl(sysmmuconp->regs + S5P_PT_BASE_ADDR);
- reg_page_ft_addr = __raw_readl(sysmmuconp->regs + S5P_PAGE_FAULT_ADDR);
-
- printk(KERN_INFO "%s: ips:%s\n", __func__, sysmmuconp->name);
- printk(KERN_INFO "%s: MMU_CTRL:0x%X, ", __func__, reg_mmu_ctrl);
- printk(KERN_INFO "MMU_STATUS:0x%X, PT_BASE_ADDR:0x%X\n", reg_mmu_status, reg_pt_base_addr);
- printk(KERN_INFO "%s: INT_STATUS:0x%X, PAGE_FAULT_ADDR:0x%X\n", __func__, reg_int_status, reg_page_ft_addr);
-
- switch (reg_int_status & 0xFF) {
- case 0x1:
- printk(KERN_INFO "%s: Page fault\n", __func__);
- printk(KERN_INFO "%s: Virtual address causing last page fault or bus error : 0x%x\n", __func__ , reg_page_ft_addr);
- break;
- case 0x2:
- printk(KERN_INFO "%s: AR multi-hit fault\n", __func__);
- break;
- case 0x4:
- printk(KERN_INFO "%s: AW multi-hit fault\n", __func__);
- break;
- case 0x8:
- printk(KERN_INFO "%s: Bus error\n", __func__);
- break;
- case 0x10:
- printk(KERN_INFO "%s: AR Security protection fault\n", __func__);
- break;
- case 0x20:
- printk(KERN_INFO "%s: AR Access protection fault\n", __func__);
- break;
- case 0x40:
- printk(KERN_INFO "%s: AW Security protection fault\n", __func__);
- break;
- case 0x80:
- printk(KERN_INFO "%s: AW Access protection fault\n", __func__);
- break;
- }
-}
-
-static irqreturn_t s5p_sysmmu_irq(int irq, void *dev_id)
-{
- unsigned int i;
- unsigned int reg_int_status;
- struct sysmmu_controller *sysmmuconp;
-
- for (i = 0; i < S5P_SYSMMU_TOTAL_IPNUM; i++) {
- sysmmuconp = &s5p_sysmmu_cntlrs[i];
-
- if (sysmmuconp->enable == true) {
- reg_int_status = __raw_readl(sysmmuconp->regs + S5P_INT_STATUS);
-
- if (reg_int_status & 0xFF)
- s5p_sysmmu_register(sysmmuconp);
- }
- }
- return IRQ_HANDLED;
-}
-
-int s5p_sysmmu_set_tablebase_pgd(sysmmu_ips ips, unsigned long pgd)
-{
- struct sysmmu_controller *sysmmuconp = NULL;
-
- sysmmuconp = &s5p_sysmmu_cntlrs[ips];
-
- if (sysmmuconp == NULL) {
- printk(KERN_ERR "failed to get ip's sysmmu info\n");
- return 1;
- }
-
- /* Set sysmmu page table base address */
- __raw_writel(pgd, sysmmuconp->regs + S5P_PT_BASE_ADDR);
-
- if (s5p_sysmmu_tlb_invalidate(ips) != 0)
- printk(KERN_ERR "failed s5p_sysmmu_tlb_invalidate\n");
-
- return 0;
-}
-
-static int s5p_sysmmu_set_tablebase(sysmmu_ips ips)
-{
- unsigned int pg;
- struct sysmmu_controller *sysmmuconp;
-
- sysmmuconp = &s5p_sysmmu_cntlrs[ips];
-
- if (sysmmuconp == NULL) {
- printk(KERN_ERR "failed to get ip's sysmmu info\n");
- return 1;
- }
-
- __asm__("mrc p15, 0, %0, c2, c0, 0" \
- : "=r" (pg) : : "cc"); \
- pg &= ~0x3fff;
-
- printk(KERN_INFO "%s: CP15 TTBR0 : 0x%x\n", __func__, pg);
-
- /* Set sysmmu page table base address */
- __raw_writel(pg, sysmmuconp->regs + S5P_PT_BASE_ADDR);
-
- return 0;
-}
-
-int s5p_sysmmu_enable(sysmmu_ips ips)
-{
- unsigned int reg;
-
- struct sysmmu_controller *sysmmuconp;
-
- sysmmuconp = &s5p_sysmmu_cntlrs[ips];
-
- if (sysmmuconp == NULL) {
- printk(KERN_ERR "failed to get ip's sysmmu info\n");
- return 1;
- }
-
- s5p_sysmmu_set_tablebase(ips);
-
- /* replacement policy : LRU */
- reg = __raw_readl(sysmmuconp->regs + S5P_MMU_CFG);
- reg |= 0x1;
- __raw_writel(reg, sysmmuconp->regs + S5P_MMU_CFG);
-
- /* Enable interrupt, Enable MMU */
- reg = __raw_readl(sysmmuconp->regs + S5P_MMU_CTRL);
- reg |= (0x1 << 2) | (0x1 << 0);
-
- __raw_writel(reg, sysmmuconp->regs + S5P_MMU_CTRL);
-
- sysmmuconp->enable = true;
-
- return 0;
-}
-
-int s5p_sysmmu_disable(sysmmu_ips ips)
-{
- unsigned int reg;
-
- struct sysmmu_controller *sysmmuconp = NULL;
-
- if (ips > S5P_SYSMMU_TOTAL_IPNUM)
- printk(KERN_ERR "failed to get ips parameter\n");
-
- sysmmuconp = &s5p_sysmmu_cntlrs[ips];
-
- if (sysmmuconp == NULL) {
- printk(KERN_ERR "failed to get ip's sysmmu info\n");
- return 1;
- }
-
- reg = __raw_readl(sysmmuconp->regs + S5P_MMU_CFG);
-
- /* replacement policy : LRU */
- reg |= 0x1;
- __raw_writel(reg, sysmmuconp->regs + S5P_MMU_CFG);
-
- reg = __raw_readl(sysmmuconp->regs + S5P_MMU_CTRL);
-
- /* Disable MMU */
- reg &= ~0x1;
- __raw_writel(reg, sysmmuconp->regs + S5P_MMU_CTRL);
-
- sysmmuconp->enable = false;
-
- return 0;
-}
-
-int s5p_sysmmu_tlb_invalidate(sysmmu_ips ips)
-{
- unsigned int reg;
- struct sysmmu_controller *sysmmuconp = NULL;
-
- sysmmuconp = &s5p_sysmmu_cntlrs[ips];
-
- if (sysmmuconp == NULL) {
- printk(KERN_ERR "failed to get ip's sysmmu info\n");
- return 1;
- }
-
- /* set Block MMU for flush TLB */
- reg = __raw_readl(sysmmuconp->regs + S5P_MMU_CTRL);
- reg |= 0x1 << 1;
- __raw_writel(reg, sysmmuconp->regs + S5P_MMU_CTRL);
-
- /* flush all TLB entry */
- __raw_writel(0x1, sysmmuconp->regs + S5P_MMU_FLUSH);
-
- /* set Un-block MMU after flush TLB */
- reg = __raw_readl(sysmmuconp->regs + S5P_MMU_CTRL);
- reg &= ~(0x1 << 1);
- __raw_writel(reg, sysmmuconp->regs + S5P_MMU_CTRL);
-
- return 0;
-}
-
-static int s5p_sysmmu_probe(struct platform_device *pdev)
-{
- int i;
- int ret;
- struct resource *res;
- struct sysmmu_controller *sysmmuconp;
- sysmmu_ips ips;
-
- for (i = 0; i < S5P_SYSMMU_TOTAL_IPNUM; i++) {
- sysmmuconp = &s5p_sysmmu_cntlrs[i];
- if (sysmmuconp == NULL) {
- printk(KERN_ERR "failed to get ip's sysmmu info\n");
- ret = -ENOENT;
- goto err_res;
- }
-
- sysmmuconp->name = sysmmu_ips_name[i];
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, i);
- if (!res) {
- printk(KERN_ERR "failed to get sysmmu resource\n");
- ret = -ENODEV;
- goto err_res;
- }
-
- sysmmuconp->mem = request_mem_region(res->start,
- ((res->end) - (res->start)) + 1, pdev->name);
- if (!sysmmuconp->mem) {
- pr_err("failed to request sysmmu memory region\n");
- ret = -EBUSY;
- goto err_res;
- }
-
- sysmmuconp->regs = ioremap(res->start, res->end - res->start + 1);
- if (!sysmmuconp->regs) {
- pr_err("failed to sysmmu ioremap\n");
- ret = -ENXIO;
- goto err_reg;
- }
-
- sysmmuconp->irq = platform_get_irq(pdev, i);
- if (sysmmuconp->irq <= 0) {
- pr_err("failed to get sysmmu irq resource\n");
- ret = -ENOENT;
- goto err_map;
- }
-
- ret = request_irq(sysmmuconp->irq, s5p_sysmmu_irq, IRQF_DISABLED, pdev->name, sysmmuconp);
- if (ret) {
- pr_err("failed to request irq\n");
- ret = -ENOENT;
- goto err_map;
- }
-
- ips = (sysmmu_ips)i;
-
- sysmmuconp->ips = ips;
- }
-
- return 0;
-
-err_reg:
- release_mem_region((resource_size_t)sysmmuconp->mem, (resource_size_t)((res->end) - (res->start) + 1));
-err_map:
- iounmap(sysmmuconp->regs);
-err_res:
- return ret;
-}
-
-static int s5p_sysmmu_remove(struct platform_device *pdev)
-{
- return 0;
-}
-int s5p_sysmmu_runtime_suspend(struct device *dev)
-{
- return 0;
-}
-
-int s5p_sysmmu_runtime_resume(struct device *dev)
-{
- return 0;
-}
-
-const struct dev_pm_ops s5p_sysmmu_pm_ops = {
- .runtime_suspend = s5p_sysmmu_runtime_suspend,
- .runtime_resume = s5p_sysmmu_runtime_resume,
-};
-
-static struct platform_driver s5p_sysmmu_driver = {
- .probe = s5p_sysmmu_probe,
- .remove = s5p_sysmmu_remove,
- .driver = {
- .owner = THIS_MODULE,
- .name = "s5p-sysmmu",
- .pm = &s5p_sysmmu_pm_ops,
- }
-};
-
-static int __init s5p_sysmmu_init(void)
-{
- return platform_driver_register(&s5p_sysmmu_driver);
-}
-arch_initcall(s5p_sysmmu_init);
+/* linux/arch/arm/plat-s5p/sysmmu.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/gfp.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+#include <linux/dma-mapping.h>
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/pm_runtime.h>
+
+#include <asm/memory.h>
+
+#include <plat/irqs.h>
+#include <plat/devs.h>
+#include <plat/cpu.h>
+#include <plat/sysmmu.h>
+
+#include <mach/map.h>
+#include <mach/regs-sysmmu.h>
+
+static int debug;
+module_param(debug, int, 0644);
+
+#define sysmmu_debug(level, fmt, arg...) \
+ do { \
+ if (debug >= level) \
+ printk(KERN_DEBUG "[%s] " fmt, __func__, ## arg);\
+ } while (0)
+
+struct s5p_sysmmu_info {
+ struct mutex mutex;
+ struct resource *ioarea;
+ void __iomem *regs;
+ unsigned int irq;
+ struct clk *clk;
+ bool enabled;
+ bool page_tables_allocated;
+ enum s5p_sysmmu_ip ip;
+ enum s5p_sysmmu_cmd mode;
+
+ unsigned long flpt;
+ unsigned long flpt_vaddr;
+ /* one table entry per 4 entries of the first level page table */
+ unsigned long *vaddr;
+ /* one table entry per 4 entries of the first level page table */
+ u16 *refcount;
+
+ struct device *dev;
+
+ struct list_head entry;
+};
+
+static LIST_HEAD(sysmmu_list);
+static DEFINE_SPINLOCK(sysmmu_list_slock);
+
+void *s5p_sysmmu_get(struct device *dev, enum s5p_sysmmu_ip ip)
+{
+ struct s5p_sysmmu_info *ret;
+ unsigned long flags;
+
+ sysmmu_debug(3, "for %s\n", dev_name(dev));
+
+ spin_lock_irqsave(&sysmmu_list_slock, flags);
+ list_for_each_entry(ret, &sysmmu_list, entry) {
+ if (ret->ip == ip) {
+ try_module_get(THIS_MODULE);
+ spin_unlock_irqrestore(&sysmmu_list_slock, flags);
+ return ret;
+ }
+ }
+ spin_unlock_irqrestore(&sysmmu_list_slock, flags);
+
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(s5p_sysmmu_get);
+
+void s5p_sysmmu_put(void *dev_id)
+{
+ module_put(THIS_MODULE);
+}
+EXPORT_SYMBOL_GPL(s5p_sysmmu_put);
+
+static void s5p_sysmmu_configure(struct s5p_sysmmu_info *sysmmu,
+ unsigned long pg)
+{
+ unsigned int reg;
+
+ writel(pg, sysmmu->regs + S5P_PT_BASE_ADDR);
+
+ reg = readl(sysmmu->regs + S5P_MMU_CFG);
+ reg |= (0x1<<0); /* replacement policy : LRU */
+ writel(reg, sysmmu->regs + S5P_MMU_CFG);
+
+ reg = readl(sysmmu->regs + S5P_MMU_CTRL);
+ reg |= ((0x1<<2)|(0x1<<0)); /* Enable interrupt, Enable MMU */
+ writel(reg, sysmmu->regs + S5P_MMU_CTRL);
+
+ sysmmu_debug(3, "CFG:0x%x\n", readl(sysmmu->regs + S5P_MMU_CFG));
+ sysmmu_debug(3, "CTRL:0x%x\n", readl(sysmmu->regs + S5P_MMU_CTRL));
+ sysmmu_debug(3, "STATUS:0x%x\n", readl(sysmmu->regs + S5P_MMU_STATUS));
+
+ sysmmu->enabled = true;
+}
+
+static int s5p_sysmmu_control_locked(struct s5p_sysmmu_info *sysmmu,
+ enum s5p_sysmmu_cmd cmd)
+{
+ unsigned int pg, reg;
+
+ sysmmu_debug(3, "%d\n", cmd);
+
+ sysmmu->mode = cmd;
+
+ switch (cmd) {
+ case S5P_SYSMMU_ENABLE_SHARED:
+ /*
+ * coprocessor 15 == mmu;
+ * copy system page tables base from there
+ */
+ __asm__("mrc p15, 0, %0, c2, c0, 0" : "=r" (pg) : : "cc");
+ pg &= ~0x3fff;
+
+ s5p_sysmmu_configure(sysmmu, pg);
+
+ return 0;
+ break;
+
+ case S5P_SYSMMU_ENABLE_PRIVATE:
+ pm_runtime_get_sync(sysmmu->dev);
+ if (!sysmmu->page_tables_allocated) {
+ /*
+ * first-level page table holds
+ * 4k second-level descriptors == 16kB == 4 pages
+ */
+ sysmmu->flpt_vaddr = (unsigned long)dma_alloc_coherent(
+ sysmmu->dev,
+ 4 * PAGE_SIZE,
+ (dma_addr_t *)&sysmmu->flpt,
+ GFP_KERNEL | __GFP_ZERO);
+ if (!sysmmu->flpt_vaddr)
+ return -ENOMEM;
+
+ sysmmu->refcount = kzalloc(1024 * sizeof(u16),
+ GFP_KERNEL);
+ if (!sysmmu->refcount) {
+ dma_free_coherent(sysmmu->dev, 4 * PAGE_SIZE,
+ (dma_addr_t *)sysmmu->flpt_vaddr,
+ sysmmu->flpt);
+ return -ENOMEM;
+ }
+
+ sysmmu->vaddr = kzalloc(1024 * sizeof(unsigned long),
+ GFP_KERNEL);
+ if (!sysmmu->vaddr) {
+ kfree(sysmmu->refcount);
+ dma_free_coherent(sysmmu->dev, 4 * PAGE_SIZE,
+ (void *)sysmmu->flpt_vaddr,
+ sysmmu->flpt);
+ return -ENOMEM;
+ }
+ sysmmu->page_tables_allocated = true;
+ }
+ s5p_sysmmu_configure(sysmmu, sysmmu->flpt);
+
+ return 0;
+ break;
+
+ case S5P_SYSMMU_DISABLE:
+ reg = readl(sysmmu->regs + S5P_MMU_CFG);
+ reg |= (0x1<<0); /* replacement policy : LRU */
+ writel(reg, sysmmu->regs + S5P_MMU_CFG);
+
+ reg = readl(sysmmu->regs + S5P_MMU_CTRL);
+ reg &= ~(0x1); /* Disable MMU */
+ writel(reg, sysmmu->regs + S5P_MMU_CTRL);
+ sysmmu->enabled = false;
+ pm_runtime_put_sync(sysmmu->dev);
+ return 0;
+ break;
+
+ case S5P_SYSMMU_TLB_INVALIDATE:
+ reg = readl(sysmmu->regs + S5P_MMU_CTRL);
+ reg |= (0x1<<1); /* Block MMU */
+ writel(reg, sysmmu->regs + S5P_MMU_CTRL);
+
+ writel(0x1, sysmmu->regs + S5P_MMU_FLUSH);
+ /* Flush_entry */
+
+ reg = readl(sysmmu->regs + S5P_MMU_CTRL);
+ reg &= ~(0x1<<1); /* Un-block MMU */
+ writel(reg, sysmmu->regs + S5P_MMU_CTRL);
+ return 0;
+ break;
+
+ default:
+ ;
+ }
+ return -EINVAL;
+}
+
+int s5p_sysmmu_control(void *dev_id, enum s5p_sysmmu_cmd cmd)
+{
+ struct s5p_sysmmu_info *sysmmu = dev_id;
+ int ret;
+
+ mutex_lock(&sysmmu->mutex);
+ ret = s5p_sysmmu_control_locked(sysmmu, cmd);
+ mutex_unlock(&sysmmu->mutex);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(s5p_sysmmu_control);
+
+#define dereference_vaddr(vaddr) (*((unsigned long *)(vaddr)))
+
+#define make_flpt_entry(slpt, k) \
+ ((((slpt) + (k) * 256 * 4) & ~0x3FF) | 0x1)
+#define make_slpt_phys_entry(phys) (((phys) & ~0xFFF) | 0x2)
+
+#define flpt_offset(vaddr) (((vaddr) >> 18) & 0x3FFC)
+#define slpt_offset(slpt, vaddr) \
+ (((slpt) & (0x3 << 10)) + (((vaddr) >> 10) & 0x3FC))
+
+#define slpt_number(vaddr) (((vaddr) >> 22) & 0x3FF)
+
+#define get_slpt(flpt_entry_vaddr) \
+ (dereference_vaddr(flpt_entry_vaddr) & ~0x3FF)
+#define get_slpt_four(flpt_entry_vaddr) \
+ (dereference_vaddr(flpt_entry_vaddr) & ~0xFFF)
+
+#define invalidate_slpt_entry(slpt_entry_vaddr) \
+ (dereference_vaddr(slpt_entry_vaddr) &= ~0x3)
+
+/*
+ * vaddr:
+ * X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X 0 0
+ * 31--------------------20 19------------12 11--------------------0
+ * index into flpt idx into slpt offset within page
+ */
+static int s5p_sysmmu_map_page(struct s5p_sysmmu_info *sysmmu,
+ unsigned long vaddr, unsigned long paddr)
+{
+ unsigned long flpt_entry_vaddr, slpt_entry_vaddr, slpt, slpt_vaddr;
+ int four_entry = slpt_number(vaddr);
+
+ flpt_entry_vaddr = sysmmu->flpt_vaddr + flpt_offset(vaddr);
+ if (0 == dereference_vaddr(flpt_entry_vaddr)) {
+ int k;
+ unsigned long flpt_four = flpt_entry_vaddr & ~0xF;
+
+ slpt_vaddr = (unsigned long)dma_alloc_coherent(
+ sysmmu->dev,
+ PAGE_SIZE,
+ (dma_addr_t *)&slpt,
+ GFP_KERNEL | __GFP_ZERO);
+ if (!slpt_vaddr)
+ return -1;
+
+ sysmmu->vaddr[four_entry] = slpt_vaddr;
+
+ for (k = 0; k < 4; ++k)
+ dereference_vaddr(flpt_four + 4 * k) =
+ make_flpt_entry(slpt, k);
+
+ sysmmu_debug(3, "4-entry:%d\n", four_entry);
+ }
+ slpt = get_slpt(flpt_entry_vaddr);
+ slpt_entry_vaddr = sysmmu->vaddr[four_entry] + slpt_offset(slpt, vaddr);
+ dereference_vaddr(slpt_entry_vaddr) = make_slpt_phys_entry(paddr);
+ sysmmu->refcount[four_entry]++;
+
+ return 0;
+}
+
+static void s5p_unmap_page(struct s5p_sysmmu_info *sysmmu, unsigned long vaddr)
+{
+ unsigned long flpt_entry_vaddr, slpt_entry_vaddr, slpt;
+ int four_entry = slpt_number(vaddr);
+
+ flpt_entry_vaddr = sysmmu->flpt_vaddr + flpt_offset(vaddr);
+ if (--sysmmu->refcount[four_entry]) {
+ slpt = get_slpt(flpt_entry_vaddr);
+ slpt_entry_vaddr = sysmmu->vaddr[four_entry] +
+ slpt_offset(slpt, vaddr);
+ invalidate_slpt_entry(slpt_entry_vaddr);
+ } else {
+ dma_free_coherent(sysmmu->dev, PAGE_SIZE,
+ (void *)sysmmu->vaddr[four_entry],
+ get_slpt_four(flpt_entry_vaddr));
+
+ memset((void *)(flpt_entry_vaddr & ~0xF), 0, 16);
+
+ sysmmu->vaddr[four_entry] = 0;
+ }
+}
+
+int s5p_sysmmu_map_area(void *dev_id, unsigned long varea_start,
+ unsigned long num_pages, struct page **pages)
+{
+ struct s5p_sysmmu_info *sysmmu = dev_id;
+ int i, ret;
+
+ sysmmu_debug(3, "varea_start:0x%lx, num_pages:%ld\n",
+ varea_start, num_pages);
+
+ mutex_lock(&sysmmu->mutex);
+ for (i = 0; i < num_pages; varea_start += PAGE_SIZE, ++i) {
+ ret = s5p_sysmmu_map_page(sysmmu,
+ varea_start, page_to_phys(pages[i]));
+ if (ret < 0)
+ goto slpt_pg_alloc_fail;
+ }
+
+ mutex_unlock(&sysmmu->mutex);
+
+ sysmmu_debug(3, "MAPPING DONE for varea_start:0x%lx, num_pages:%ld\n",
+ varea_start - num_pages * PAGE_SIZE, num_pages);
+
+ return 0;
+
+slpt_pg_alloc_fail:
+ while (--i >= 0) {
+ varea_start -= PAGE_SIZE;
+ s5p_unmap_page(sysmmu, varea_start);
+ }
+ s5p_sysmmu_control_locked(sysmmu, S5P_SYSMMU_TLB_INVALIDATE);
+ mutex_unlock(&sysmmu->mutex);
+ return -1;
+}
+EXPORT_SYMBOL_GPL(s5p_sysmmu_map_area);
+
+int s5p_sysmmu_map_phys_area(void *dev_id, unsigned long varea_start,
+ unsigned long phys_area_start, unsigned long num_pages)
+{
+ struct s5p_sysmmu_info *sysmmu = dev_id;
+ int i;
+
+ sysmmu_debug(3, "varea_start:0x%lx, num_pages:%ld\n",
+ varea_start, num_pages);
+
+ mutex_lock(&sysmmu->mutex);
+ for (i = 0; i < num_pages;
+ varea_start += PAGE_SIZE, phys_area_start += PAGE_SIZE, ++i)
+ if (s5p_sysmmu_map_page(sysmmu, varea_start, phys_area_start) < 0)
+ goto slpt_pg_alloc_fail;
+
+ mutex_unlock(&sysmmu->mutex);
+
+ sysmmu_debug(3, "MAPPING DONE for varea_start:0x%lx, num_pages:%ld\n",
+ varea_start - num_pages * PAGE_SIZE, num_pages);
+
+ return 0;
+
+slpt_pg_alloc_fail:
+ while (--i >= 0) {
+ varea_start -= PAGE_SIZE;
+ s5p_unmap_page(sysmmu, varea_start);
+ }
+ s5p_sysmmu_control_locked(sysmmu, S5P_SYSMMU_TLB_INVALIDATE);
+ mutex_unlock(&sysmmu->mutex);
+ return -1;
+}
+EXPORT_SYMBOL_GPL(s5p_sysmmu_map_phys_area);
+
+void s5p_sysmmu_unmap_area(void *dev_id, unsigned long varea_start,
+ unsigned long num_pages)
+{
+ struct s5p_sysmmu_info *sysmmu = dev_id;
+ unsigned long vaddr = varea_start;
+ int i;
+
+ mutex_lock(&sysmmu->mutex);
+
+ sysmmu_debug(3, "varea_start:0x%lx, num_pages:%ld\n",
+ varea_start, num_pages);
+
+ for (i = 0; i < num_pages; vaddr += PAGE_SIZE, ++i)
+ s5p_unmap_page(sysmmu, vaddr);
+
+ s5p_sysmmu_control_locked(sysmmu, S5P_SYSMMU_TLB_INVALIDATE);
+ mutex_unlock(&sysmmu->mutex);
+
+ sysmmu_debug(3, "UNMAPPING DONE for varea_start:0x%lx, num_pages:%ld\n",
+ varea_start, num_pages);
+
+ return;
+}
+EXPORT_SYMBOL_GPL(s5p_sysmmu_unmap_area);
+
+static void s5p_sysmmu_pg_fault(struct s5p_sysmmu_info *sysmmu)
+{
+ void __iomem *regbase = sysmmu->regs;
+ unsigned long fault;
+
+ fault = readl(regbase + S5P_PAGE_FAULT_ADDR);
+ sysmmu_debug(3, "Page fault occured for virtual address 0x%08lx\n",
+ fault);
+}
+
+static irqreturn_t s5p_sysmmu_irq(int irq, void *dev_id)
+{
+ struct s5p_sysmmu_info *sysmmu = dev_id;
+ unsigned int reg_INT_STATUS;
+
+ if (false == sysmmu->enabled)
+ return IRQ_HANDLED;
+
+ reg_INT_STATUS = readl(sysmmu->regs + S5P_INT_STATUS);
+ if (reg_INT_STATUS & 0xFF) {
+ switch (reg_INT_STATUS & 0xFF) {
+ case 0x1:
+ /* page fault */
+ sysmmu_debug(3, "irq:pg fault\n");
+ s5p_sysmmu_pg_fault(sysmmu);
+ break;
+ case 0x2:
+ /* AR multi-hit fault */
+ sysmmu_debug(3, "irq:ar multi hit\n");
+ break;
+ case 0x4:
+ /* AW multi-hit fault */
+ sysmmu_debug(3, "irq:aw multi hit\n");
+ break;
+ case 0x8:
+ /* bus error */
+ sysmmu_debug(3, "irq:bus error\n");
+ break;
+ case 0x10:
+ /* AR security protection fault */
+ sysmmu_debug(3, "irq:ar security protection fault\n");
+ break;
+ case 0x20:
+ /* AR access protection fault */
+ sysmmu_debug(3, "irq:ar access protection fault\n");
+ break;
+ case 0x40:
+ /* AW security protection fault */
+ sysmmu_debug(3, "irq:aw security protection fault\n");
+ break;
+ case 0x80:
+ /* AW access protection fault */
+ sysmmu_debug(3, "irq:aw access protection fault\n");
+ break;
+ }
+ writel(reg_INT_STATUS, sysmmu->regs + S5P_INT_CLEAR);
+ }
+ return IRQ_HANDLED;
+}
+
+static int s5p_sysmmu_probe(struct platform_device *pdev)
+{
+ struct s5p_sysmmu_info *sysmmu;
+ struct resource *res;
+ int ret;
+ unsigned long flags;
+
+ sysmmu = kzalloc(sizeof(struct s5p_sysmmu_info), GFP_KERNEL);
+ if (!sysmmu) {
+ dev_err(&pdev->dev, "no memory for state\n");
+ return -ENOMEM;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (NULL == res) {
+ dev_err(&pdev->dev, "cannot find IO resource\n");
+ ret = -ENOENT;
+ goto err_s5p_sysmmu_info_allocated;
+ }
+
+ sysmmu->ioarea = request_mem_region(res->start, resource_size(res),
+ pdev->name);
+
+ if (NULL == sysmmu->ioarea) {
+ dev_err(&pdev->dev, "cannot request IO\n");
+ ret = -ENXIO;
+ goto err_s5p_sysmmu_info_allocated;
+ }
+
+ sysmmu->regs = ioremap(res->start, resource_size(res));
+
+ if (NULL == sysmmu->regs) {
+ dev_err(&pdev->dev, "cannot map IO\n");
+ ret = -ENXIO;
+ goto err_ioarea_requested;
+ }
+
+ dev_dbg(&pdev->dev, "registers %p (%p, %p)\n",
+ sysmmu->regs, sysmmu->ioarea, res);
+
+ sysmmu->irq = ret = platform_get_irq(pdev, 0);
+ if (ret <= 0) {
+ dev_err(&pdev->dev, "cannot find IRQ\n");
+ goto err_iomap_done;
+ }
+
+ ret = request_irq(sysmmu->irq, s5p_sysmmu_irq, 0,
+ dev_name(&pdev->dev), sysmmu);
+
+ if (ret != 0) {
+ dev_err(&pdev->dev, "cannot claim IRQ %d\n", sysmmu->irq);
+ goto err_iomap_done;
+ }
+
+ sysmmu->clk = clk_get(&pdev->dev, "sysmmu");
+ if (IS_ERR_OR_NULL(sysmmu->clk)) {
+ dev_err(&pdev->dev, "cannot get clock\n");
+ ret = -ENOENT;
+ goto err_request_irq_done;
+ }
+ dev_dbg(&pdev->dev, "clock source %p\n", sysmmu->clk);
+ clk_enable(sysmmu->clk);
+
+ sysmmu->ip = pdev->id;
+
+ spin_lock_irqsave(&sysmmu_list_slock, flags);
+ list_add(&sysmmu->entry, &sysmmu_list);
+ spin_unlock_irqrestore(&sysmmu_list_slock, flags);
+
+ sysmmu->dev = &pdev->dev;
+
+ mutex_init(&sysmmu->mutex);
+
+ platform_set_drvdata(pdev, sysmmu);
+
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+
+ dev_info(&pdev->dev, "Samsung S5P SYSMMU (IOMMU)\n");
+ return 0;
+
+err_request_irq_done:
+ free_irq(sysmmu->irq, sysmmu);
+
+err_iomap_done:
+ iounmap(sysmmu->regs);
+
+err_ioarea_requested:
+ release_resource(sysmmu->ioarea);
+ kfree(sysmmu->ioarea);
+
+err_s5p_sysmmu_info_allocated:
+ kfree(sysmmu);
+ return ret;
+}
+
+static int s5p_sysmmu_remove(struct platform_device *pdev)
+{
+ struct s5p_sysmmu_info *sysmmu = platform_get_drvdata(pdev);
+ unsigned long flags;
+ int i = 1024;
+
+ pm_runtime_disable(sysmmu->dev);
+
+ if ((S5P_SYSMMU_ENABLE_PRIVATE == sysmmu->mode)) {
+ while (i >= 0) {
+ if (sysmmu->refcount[i]) {
+ unsigned long flpt_entry;
+ flpt_entry = dereference_vaddr(
+ sysmmu->flpt_vaddr + 4 * 4 * i);
+ dma_free_coherent(sysmmu->dev,
+ PAGE_SIZE,
+ (void *)sysmmu->vaddr[i],
+ flpt_entry & ~0xFFF);
+ }
+ --i;
+ }
+
+ if (sysmmu->flpt) {
+ dma_free_coherent(sysmmu->dev, 4 * PAGE_SIZE,
+ (void *)sysmmu->flpt_vaddr, sysmmu->flpt);
+ }
+ kfree(sysmmu->refcount);
+ kfree(sysmmu->vaddr);
+ }
+
+ spin_lock_irqsave(&sysmmu_list_slock, flags);
+ list_del(&sysmmu->entry);
+ spin_unlock_irqrestore(&sysmmu_list_slock, flags);
+
+ clk_disable(sysmmu->clk);
+ clk_put(sysmmu->clk);
+
+ free_irq(sysmmu->irq, sysmmu);
+
+ iounmap(sysmmu->regs);
+
+ release_resource(sysmmu->ioarea);
+ kfree(sysmmu->ioarea);
+
+ kfree(sysmmu);
+
+ return 0;
+}
+
+static int s5p_sysmmu_runtime_suspend(struct device *dev)
+{
+ return 0;
+}
+
+static int s5p_sysmmu_runtime_resume(struct device *dev)
+{
+ return 0;
+}
+
+static int s5p_sysmmu_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ return 0;
+}
+
+static int s5p_sysmmu_resume(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static const struct dev_pm_ops s5p_sysmmu_pm_ops = {
+ .runtime_suspend = s5p_sysmmu_runtime_suspend,
+ .runtime_resume = s5p_sysmmu_runtime_resume,
+};
+
+static struct platform_driver s5p_sysmmu_driver = {
+ .probe = s5p_sysmmu_probe,
+ .remove = s5p_sysmmu_remove,
+ .suspend = s5p_sysmmu_suspend,
+ .resume = s5p_sysmmu_resume,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "s5p-sysmmu",
+ .pm = &s5p_sysmmu_pm_ops,
+ },
+};
+
+static int __init s5p_sysmmu_register(void)
+{
+ return platform_driver_register(&s5p_sysmmu_driver);
+}
+
+static void __exit s5p_sysmmu_unregister(void)
+{
+ platform_driver_unregister(&s5p_sysmmu_driver);
+}
+
+module_init(s5p_sysmmu_register);
+module_exit(s5p_sysmmu_unregister);
+
+MODULE_AUTHOR("Andrzej Pietrasiewicz <andrzej.p@samsung.com>");
+MODULE_DESCRIPTION("Samsung System MMU (IOMMU) driver");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h
index b0123f3..9f42dee 100644
--- a/arch/arm/plat-samsung/include/plat/devs.h
+++ b/arch/arm/plat-samsung/include/plat/devs.h
@@ -138,7 +138,7 @@ extern struct platform_device s5p_device_fimc3;
extern struct platform_device s5p_device_mipi_csis0;
extern struct platform_device s5p_device_mipi_csis1;
-extern struct platform_device s5pv310_device_sysmmu;
+extern struct platform_device s5pv310_device_sysmmu[];
/* s3c2440 specific devices */
--
1.7.1.569.g6f426
^ permalink raw reply related [flat|nested] 29+ messages in thread
* [PATCH/RFC 0/7] Samsung IOMMU videobuf2 allocator and s5p-fimc update
2011-03-04 9:01 [PATCH/RFC 0/7] Samsung IOMMU videobuf2 allocator and s5p-fimc update Marek Szyprowski
` (6 preceding siblings ...)
2011-03-04 9:01 ` [PATCH 7/7] ARM: S5PC210: enable FIMC on Universal_C210 Marek Szyprowski
@ 2011-03-08 7:28 ` Kukjin Kim
2011-03-08 9:34 ` Marek Szyprowski
7 siblings, 1 reply; 29+ messages in thread
From: Kukjin Kim @ 2011-03-08 7:28 UTC (permalink / raw)
To: linux-arm-kernel
Hello,
There are comments for your System MMU driver below.
It's good that System MMU has functionality of mapping but System MMU have
to use other mapping of virtual memory allocator.
And would be better to change sysmmu_list to use array of defined in
s5p_sysmmu_ip enumeration, so that can get enhancement of memory space
usage, speed, and readability of codes.
TLB replacement policy does not need to use LRU. Of course, current System
MMU also needs it. I think, the round robin is enough, because to access
memory has no temporal locality and to make LRU need to access to System
MMU register one more. The reset value is round robin.
In the setting of SHARED page table in s5p_sysmmu_control_locked, get the
page table base address of ARM core from cp15 register now. But current->mm-
>pgd is better for more compatibility.
When it make page table with PRIVATE page table methods, the size of the
structure to manage the second page table is quite big. It is much better
rather that to make slab with cache size of 1KB.
Besides, the page mapping implementation is not safe in your System MMU
driver. Because only first one confirms primary page table entry, when it
assigns four second page tables consecutively at a time.
The System MMU driver cannot apply runtime pm by oneself with calling
pm_runtime_put_sync(). The reason is because a device with System MMU can
on/off power. I think just clock gating is enough. However, I can't find
clock enable/disable in your driver.
By PRIVATE page table method, each system MMU comes to have a page table
only for oneself. In this case, the problem is that each MFC System MMU L
and R having another page table.
In your System MMU driver, the page size is always 4KB crucially. This says
TLB thrashing and produces a result to lose a TLB hit rate. It is a big
problem with the device such as rotator which does not do sequential access
especially.
And the IRQ handler just outputs only a message. It should be implemented
in call back function to be able to handle from each device driver.
When it sets System MMU in SHARED page table, kernel virtual memory is
broken by a method such as s5p_sysmmu_map_area() :(
Thanks.
Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.
Marek Szyprowski wrote:
>
> Hello,
>
> This patch series introduces new type of videbuf2 memory allocator -
> vb2-s5p-iommu. This allocator can be used only on Samsung SoCs that have
> IOMMU module. Currently only Samsung EXYNOS4 (former S5PV310) platform
> has SYSMMU modules. The allocator is then used by s5p-fimc driver. To
> make it possible some additional changes are required. Mainly platform
> support for s5p-fimc for EXYNOS4 machines need to be defined. The
> proposed solution has been tested on Universal C210 board (Samsung
> S5PC210/EXYNOS4 based).
>
> We decided to use driver private address space mode of the iommu driver.
> This way each vb2-s5p-iommu client gets it's own address space for
> memory buffers. This reduces kernel virtual memory fragmentation as well
> as solves some non-trivial page table updates issues. The drawback is
> the fact that the interface for s5p-sysmmu has been changed.
>
> This IOMMU allocator has no dependences on other subsystems besides
> Samsung platfrom core. We also ported s5p-mfc and s5p-tv drivers to this
> allocator, they will be posted in separate patch series. This will
> enable to get them working on EXYNOS4 (S5PV310) platform. Support for
> S5PV210/S5PC110 platform still depends on CMA allocator that needs more
> discussion on memory management mailing list and development. The
> patches with updated s5p-mfc and s5p-tv drivers will follow.
>
> To get FIMC module working on EXYNOS4/UniversalC210 board we also added
> support for power domains and power gating.
>
> This patch series contains a collection of patches for various platform
> subsystems. Here is a detailed list:
>
> [PATCH 1/7] ARM: S5PV310: Add platform definitions for FIMC
> - adds basic platform resources for FIMC modules (for s5p-fimc driver)
>
> [PATCH 2/7] ARM: S5PV310: power domains: fixes and code cleanup
> - adds support for block gating in Samsung power domain driver and
> performs some cleanup
>
> [PATCH 3/7] ARM: Samsung: update/rewrite Samsung SYSMMU (IOMMU) driver
> - a complete rewrite of sysmmu driver for Samsung platform:
> - the new version introduces device private page tables (address space)
> mode
> - simplified the resource management (no more horrible single platform
> device with 32 resources is needed)
> - some other API chages required by upcoming videobuf2 allocator
>
> [PATCH 4/7] v4l: videobuf2: add Samsung SYSMMU (IOMMU) based allocator
> - introduces new memory allocator for videobuf2, it uses s5p-sysmmu
> iommu driver, memory for video buffers is acuired by alloc_page() kernel
> function
>
> [PATCH 5/7] s5p-fimc: add pm_runtime support
> - adds support for pm_runtime in s5p-fimc driver
>
> [PATCH 6/7] s5p-fimc: Add support for vb2-s5p-iommu allocator
> - adds support for the newly introduces videbuf2-s5p-iommu allocator
> on EXYNOS4 platform
>
> [PATCH 7/7] ARM: S5PC210: enable FIMC on Universal_C210
> - adds all required machine definitions to get FIMC modules working
> on Universal C210 boards
>
>
> The patch series is based on git://linuxtv.org/media_tree.git tree,
> staging/for_v2.6.39 branch with the following Samsung platform patches:
> 1. [PATCH] ARM: Samsung: change suspend/resume code to depend on
> CONFIG_SUSPEND
> http://www.mail-archive.com/linux-samsung-
soc at vger.kernel.org/msg04025.html
> 2. [PATCH v2] ARM: S5PC210: add support for i2c PMICs on Universal_C210
board
> http://www.mail-archive.com/linux-samsung-
soc at vger.kernel.org/msg04029.html
>
> This series has not been rebased onto the latest changes (S5PV310
> renamed to EXYNOS4) in
> git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git,
> for-next branch. We will rebase them soon, but first we want to get
> feedback and comments on the s5p-iommu videobuf2 allocator idea.
>
> Best regards
> --
> Marek Szyprowski
> Samsung Poland R&D Center
>
>
> Complete patch summary:
>
> Andrzej Pietrasiewicz (2):
> ARM: Samsung: update/rewrite Samsung SYSMMU (IOMMU) driver
> v4l: videobuf2: add Samsung SYSMMU (IOMMU) based allocator
>
> Marek Szyprowski (3):
> s5p-fimc: add pm_runtime support
> s5p-fimc: Add support for vb2-s5p-iommu allocator
> ARM: S5PC210: enable FIMC on Universal_C210
>
> Sylwester Nawrocki (1):
> ARM: S5PV310: Add platform definitions for FIMC
>
> Tomasz Stanislawski (1):
> ARM: S5PV310: power domains: fixes and code cleanup
>
> arch/arm/mach-s5pv310/Kconfig | 6 +
> arch/arm/mach-s5pv310/clock.c | 91 ++
> arch/arm/mach-s5pv310/cpu.c | 7 +
> arch/arm/mach-s5pv310/dev-pd.c | 93 ++-
> arch/arm/mach-s5pv310/dev-sysmmu.c | 582 +++++++++----
> arch/arm/mach-s5pv310/include/mach/irqs.h | 40 +-
> arch/arm/mach-s5pv310/include/mach/map.h | 8 +
> arch/arm/mach-s5pv310/include/mach/regs-clock.h | 12 +
> arch/arm/mach-s5pv310/include/mach/regs-sysmmu.h | 23 +-
> arch/arm/mach-s5pv310/include/mach/sysmmu.h | 122 ---
> arch/arm/mach-s5pv310/mach-universal_c210.c | 20 +
> arch/arm/plat-s5p/Kconfig | 22 +-
> arch/arm/plat-s5p/Makefile | 1 +
> arch/arm/plat-s5p/dev-fimc3.c | 43 +
> arch/arm/plat-s5p/include/plat/sysmmu.h | 127 +++
> arch/arm/plat-s5p/sysmmu.c | 988 +++++++++++++++--
---
> --
> arch/arm/plat-samsung/include/plat/devs.h | 3 +-
> arch/arm/plat-samsung/include/plat/fimc-core.h | 5 +
> arch/arm/plat-samsung/include/plat/pd.h | 1 +
> drivers/media/video/Kconfig | 11 +-
> drivers/media/video/Makefile | 1 +
> drivers/media/video/s5p-fimc/fimc-capture.c | 9 +-
> drivers/media/video/s5p-fimc/fimc-core.c | 36 +-
> drivers/media/video/s5p-fimc/fimc-mem.h | 87 ++
> drivers/media/video/videobuf2-s5p-iommu.c | 444 ++++++++++
> include/media/videobuf2-s5p-iommu.h | 50 ++
> 26 files changed, 2129 insertions(+), 703 deletions(-)
> rewrite arch/arm/mach-s5pv310/dev-sysmmu.c (86%)
> delete mode 100644 arch/arm/mach-s5pv310/include/mach/sysmmu.h
> create mode 100644 arch/arm/plat-s5p/dev-fimc3.c
> create mode 100644 arch/arm/plat-s5p/include/plat/sysmmu.h
> rewrite arch/arm/plat-s5p/sysmmu.c (85%)
> create mode 100644 drivers/media/video/s5p-fimc/fimc-mem.h
> create mode 100644 drivers/media/video/videobuf2-s5p-iommu.c
> create mode 100644 include/media/videobuf2-s5p-iommu.h
>
> --
> 1.7.1.569.g6f426
^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH/RFC 0/7] Samsung IOMMU videobuf2 allocator and s5p-fimc update
2011-03-08 7:28 ` [PATCH/RFC 0/7] Samsung IOMMU videobuf2 allocator and s5p-fimc update Kukjin Kim
@ 2011-03-08 9:34 ` Marek Szyprowski
2011-03-08 10:05 ` InKi Dae
0 siblings, 1 reply; 29+ messages in thread
From: Marek Szyprowski @ 2011-03-08 9:34 UTC (permalink / raw)
To: linux-arm-kernel
Hello,
On Tuesday, March 08, 2011 8:29 AM Kukjin Kim wrote:
> Hello,
>
> There are comments for your System MMU driver below.
Please take into account that this was an initial version of our SYSMMU
driver to start the discussion, so there were a few minor problems left.
Thanks for pointing them out btw. :)
> It's good that System MMU has functionality of mapping but System MMU have
> to use other mapping of virtual memory allocator.
Could you elaborate on this? I'm not sure I understand right your problem.
SYSMMU driver is a low-level driver for the SYSMMU module. The driver should
provide all the basic functionality that is (or might be) hardware dependent.
Creating a mapping is one of such elementary functionalities. Sysmmu client
(let it be videobuf2-s5p-iommu, vcmm, maybe even other driver directly)
should not need to know the format of page descriptors or the way they are
arranged in the memory. The sysmmu should provide low level functions to create
and remove a mapping. Managing a virtual space is something that MIGHT be client
dependent and should be left to the client.
This design allows for different approaches to coexist. Videobuf2-s5p-iommu
client will manage the virtual space with gen_alloc framework, while vcmm will
use its own methods.
It would be great if one decide to unify iommu interfaces across the kernel,
but this will be a long road. We need to start from something simple (platform
private) and working first.
> And would be better to change sysmmu_list to use array of defined in
> s5p_sysmmu_ip enumeration, so that can get enhancement of memory space
> usage, speed, and readability of codes.
Yes, the list can be simplified to an array, but this is really a minor issue.
> TLB replacement policy does not need to use LRU. Of course, current System
> MMU also needs it. I think, the round robin is enough, because to access
> memory has no temporal locality and to make LRU need to access to System
> MMU register one more. The reset value is round robin.
Well, the best possibility is to allow sysmmu clients to decide which policy
should be used. For some devices (I'm thinking of MFC) LRU policy might give
a little speedup.
> In the setting of SHARED page table in s5p_sysmmu_control_locked, get the
> page table base address of ARM core from cp15 register now. But current->mm-
> >pgd is better for more compatibility.
Right, this way the pgd table pointer can be acquired in a more system friendly
way.
> When it make page table with PRIVATE page table methods, the size of the
> structure to manage the second page table is quite big. It is much better
> rather that to make slab with cache size of 1KB.
Yes, our initial driver uses directly 4KB pages to manage 4 consecutive second
page tables. However usually the allocations of client devices will be few but
quite large each. So most of pages used to hold second level page tables will
be effectively reused.
You are right however that the approach with a slab with 1KB units will
result in code that is cleaner and easier to understand.
> Besides, the page mapping implementation is not safe in your System MMU
> driver. Because only first one confirms primary page table entry, when it
> assigns four second page tables consecutively at a time.
That's a direct result of the 4-second-level-at-once method of allocating
second level pages, but this can be cleaned by using 1KB with slab.
> The System MMU driver cannot apply runtime pm by oneself with calling
> pm_runtime_put_sync(). The reason is because a device with System MMU can
> on/off power. I think just clock gating is enough. However, I can't find
> clock enable/disable in your driver.
Clock is enabled in probe() and disabled in remove(). pm_runtime_get/put_sync()
only increases/decreases use count of a respective power domain, so the actual
device driver also has to call pm_runtime_get/put. Calling pm_runtime_put_sync()
will not shut down the power if the sysmmu client driver has called
pm_runtime_get() without pm_runtime_put(). I see no problems here. Could you
elaborate your issue?
>
> By PRIVATE page table method, each system MMU comes to have a page table
> only for oneself. In this case, the problem is that each MFC System MMU L
> and R having another page table.
Yes, true. This is consequence of the MFC hardware design and the fact that
it has 2 AXI master interfaces and 2 SYSMMU controllers. Each of them have to
be configured separately. Each of them has a separate virtual driver's address
space. Such configuration is used by the MFC driver posted in v7 patch series.
> In your System MMU driver, the page size is always 4KB crucially. This says
> TLB thrashing and produces a result to lose a TLB hit rate. It is a big
> problem with the device such as rotator which does not do sequential access
> especially.
The page size is set to 4KB, because Linux kernel uses 4KB pages by default.
Once support for other page size is available in the kernel, then sysmmu can be
extended also.
> And the IRQ handler just outputs only a message. It should be implemented
> in call back function to be able to handle from each device driver.
This was only for debugging purpose, but you are right that the sysmmu API in
this area need to be extended.
> When it sets System MMU in SHARED page table, kernel virtual memory is
> broken by a method such as s5p_sysmmu_map_area()
Yes, there should be a check added to prevent messing with ARM pgd in SHARED
mode.
Best regards
--
Marek Szyprowski
Samsung Poland R&D Center
^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH/RFC 0/7] Samsung IOMMU videobuf2 allocator and s5p-fimc update
2011-03-08 9:34 ` Marek Szyprowski
@ 2011-03-08 10:05 ` InKi Dae
0 siblings, 0 replies; 29+ messages in thread
From: InKi Dae @ 2011-03-08 10:05 UTC (permalink / raw)
To: linux-arm-kernel
Hello, Mr. Kukjin.
2011/3/8 Marek Szyprowski <m.szyprowski@samsung.com>:
> Hello,
>
> On Tuesday, March 08, 2011 8:29 AM Kukjin Kim wrote:
>
>> Hello,
>>
>> There are comments for your System MMU driver below.
>
> Please take into account that this was an initial version of our SYSMMU
> driver to start the discussion, so there were a few minor problems left.
> Thanks for pointing them out btw. :)
>
>
>> It's good that System MMU has functionality of mapping but System MMU have
>> to use other mapping of virtual memory allocator.
>
you mean that other page sizes such as large, small page and so on
should be supported in mapping also? otherwise use 64k not 4k page?
> Could you elaborate on this? I'm not sure I understand right your problem.
>
> SYSMMU driver is a low-level driver for the SYSMMU module. The driver should
> provide all the basic functionality that is (or might be) hardware dependent.
> Creating a mapping is one of such elementary functionalities. Sysmmu client
> (let it be videobuf2-s5p-iommu, vcmm, maybe even other driver directly)
> should not need to know the format of page descriptors or the way they are
> arranged in the memory. The sysmmu should provide low level functions to create
> and remove a mapping. Managing a virtual space is something that MIGHT be client
> dependent and should be left to the client.
>
> This design allows for different approaches to coexist. Videobuf2-s5p-iommu
> client will manage the virtual space with gen_alloc framework, while vcmm will
> use its own methods.
>
> It would be great if one decide to unify iommu interfaces across the kernel,
> but this will be a long road. We need to start from something simple (platform
> private) and working first.
>
>> And would be better to change sysmmu_list to use array of defined in
>> s5p_sysmmu_ip enumeration, so that can get enhancement of memory space
>> usage, speed, and readability of codes.
>
> Yes, the list can be simplified to an array, but this is really a minor issue.
>
>> TLB replacement policy does not need to use LRU. Of course, current System
>> MMU also needs it. I think, the round robin is enough, because to access
>> memory has no temporal locality and to make LRU need to access to System
>> MMU register one more. The reset value is round robin.
>
> Well, the best possibility is to allow sysmmu clients to decide which policy
> should be used. For some devices (I'm thinking of MFC) LRU policy might give
> a little speedup.
>
>> In the setting of SHARED page table in s5p_sysmmu_control_locked, get the
>> page table base address of ARM core from cp15 register now. But current->mm-
>> >pgd is better for more compatibility.
>
> Right, this way the pgd table pointer can be acquired in a more system friendly
> way.
>
>> When it make page table with PRIVATE page table methods, the size of the
>> structure to manage the second page table is quite big. It is much better
>> rather that to make slab with cache size of 1KB.
>
> Yes, our initial driver uses directly 4KB pages to manage 4 consecutive second
> page tables. However usually the allocations of client devices will be few but
> quite large each. So most of pages used to hold second level page tables will
> be effectively reused.
>
> You are right however that the approach with a slab with 1KB units will
> result in code that is cleaner and easier to understand.
>
>> Besides, the page mapping implementation is not safe in your System MMU
>> driver. Because only first one confirms primary page table entry, when it
>> assigns four second page tables consecutively at a time.
>
> That's a direct result of the 4-second-level-at-once method of allocating
> second level pages, but this can be cleaned by using 1KB with slab.
>
>> The System MMU driver cannot apply runtime pm by oneself with calling
>> pm_runtime_put_sync(). The reason is because a device with System MMU can
>> on/off power. I think just clock gating is enough. However, I can't find
>> clock enable/disable in your driver.
>
> Clock is enabled in probe() and disabled in remove(). pm_runtime_get/put_sync()
> only increases/decreases use count of a respective power domain, so the actual
> device driver also has to call pm_runtime_get/put. Calling pm_runtime_put_sync()
> will not shut down the power if the sysmmu client driver has called
> pm_runtime_get() without pm_runtime_put(). I see no problems here. Could you
> elaborate your issue?
>
>>
>> By PRIVATE page table method, each system MMU comes to have a page table
>> only for oneself. In this case, the problem is that each MFC System MMU L
>> and R having another page table.
>
> Yes, true. This is consequence of the MFC hardware design and the fact that
> it has 2 AXI master interfaces and 2 SYSMMU controllers. Each of them have to
> be configured separately. Each of them has a separate virtual driver's address
> space. Such configuration is used by the MFC driver posted in v7 patch series.
>
>> In your System MMU driver, the page size is always 4KB crucially. This says
>> TLB thrashing and produces a result to lose a TLB hit rate. It is a big
>> problem with the device such as rotator which does not do sequential access
>> especially.
>
> The page size is set to 4KB, because Linux kernel uses 4KB pages by default.
> Once support for other page size is available in the kernel, then sysmmu can be
> extended also.
>
>> And the IRQ handler just outputs only a message. It should be implemented
>> in call back function to be able to handle from each device driver.
>
> This was only for debugging purpose, but you are right that the sysmmu API in
> this area need to be extended.
>
>> When it sets System MMU in SHARED page table, kernel virtual memory is
>> broken by a method such as s5p_sysmmu_map_area()
>
> Yes, there should be a check added to prevent messing with ARM pgd in SHARED
> mode.
>
> Best regards
> --
> Marek Szyprowski
> Samsung Poland R&D Center
>
>
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>
^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH 3/7] ARM: Samsung: update/rewrite Samsung SYSMMU (IOMMU) driver
2011-03-04 16:04 ` Marek Szyprowski
@ 2011-03-10 14:52 ` Arnd Bergmann
2011-03-11 9:04 ` Marek Szyprowski
0 siblings, 1 reply; 29+ messages in thread
From: Arnd Bergmann @ 2011-03-10 14:52 UTC (permalink / raw)
To: linux-arm-kernel
On Friday 04 March 2011, Marek Szyprowski wrote:
> From: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
>
> This patch performs a complete rewrite of sysmmu driver for Samsung platform:
> - the new version introduces an api to construct device private page
> tables and enables to use device private address space mode
> - simplified the resource management: no more single platform
> device with 32 resources is needed, better fits into linux driver model,
> each sysmmu instance has it's own resource definition
> - added support for sysmmu clocks
> - some other minor API chages required by upcoming videobuf2 allocator
>
> Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Please explain why create a new IOMMU API when we already have two
generic ones (include/linux/iommu.h and include/linux/dma-mapping.h).
Is there something that cannot be done with the common code?
The first approach should be to extend the existing APIs to
do what you need.
Arnd
^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH 3/7] ARM: Samsung: update/rewrite Samsung SYSMMU (IOMMU) driver
2011-03-10 14:52 ` Arnd Bergmann
@ 2011-03-11 9:04 ` Marek Szyprowski
2011-03-11 11:50 ` Arnd Bergmann
0 siblings, 1 reply; 29+ messages in thread
From: Marek Szyprowski @ 2011-03-11 9:04 UTC (permalink / raw)
To: linux-arm-kernel
Hello,
On Thursday, March 10, 2011 3:52 PM Arnd Bergmann wrote:
> On Friday 04 March 2011, Marek Szyprowski wrote:
> > From: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
> >
> > This patch performs a complete rewrite of sysmmu driver for Samsung platform:
> > - the new version introduces an api to construct device private page
> > tables and enables to use device private address space mode
> > - simplified the resource management: no more single platform
> > device with 32 resources is needed, better fits into linux driver model,
> > each sysmmu instance has it's own resource definition
> > - added support for sysmmu clocks
> > - some other minor API chages required by upcoming videobuf2 allocator
> >
> > Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
> > Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> > Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
>
> Please explain why create a new IOMMU API when we already have two
> generic ones (include/linux/iommu.h and include/linux/dma-mapping.h).
>
> Is there something that cannot be done with the common code?
> The first approach should be to extend the existing APIs to
> do what you need.
We followed the style of iommu API for other mainline ARM platforms (both OMAP and MSM
also have custom API for their iommu modules). I've briefly checked include/linux/iommu.h
API and I've noticed that it has been designed mainly for KVM support. There is also
include/linux/intel-iommu.h interface, but I it is very specific to intel gfx chips.
Is there any example how include/linux/dma-mapping.h interface can be used for iommu
mappings?
Best regards
--
Marek Szyprowski
Samsung Poland R&D Center
^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH 3/7] ARM: Samsung: update/rewrite Samsung SYSMMU (IOMMU) driver
2011-03-11 9:04 ` Marek Szyprowski
@ 2011-03-11 11:50 ` Arnd Bergmann
2011-03-11 12:35 ` Marek Szyprowski
0 siblings, 1 reply; 29+ messages in thread
From: Arnd Bergmann @ 2011-03-11 11:50 UTC (permalink / raw)
To: linux-arm-kernel
On Friday 11 March 2011, Marek Szyprowski wrote:
>
> We followed the style of iommu API for other mainline ARM platforms (both OMAP and MSM
> also have custom API for their iommu modules). I've briefly checked include/linux/iommu.h
> API and I've noticed that it has been designed mainly for KVM support. There is also
> include/linux/intel-iommu.h interface, but I it is very specific to intel gfx chips.
The MSM code actually uses the generic iommu.h code, using register_iommu, so
the drivers can use the regular iommu_map.
I believe the omap code predates the iommu API, and should really be changed
to use that. At least it was added before I started reviewing the code.
The iommu API is not really meant to be KVM specific, it's just that the
in-tree users are basically limited to KVM at the moment. Another user that
is coming up soon is the vmio device driver that can be used to transparently
pass devices to user space. The idea behind the IOMMU API is that you can
map arbitrary bus addresses to physical memory addresses, but it does not
deal with allocating the bus addresses or providing buffer management such
as cache flushes.
> Is there any example how include/linux/dma-mapping.h interface can be used for iommu
> mappings?
The dma-mapping API is the normal interface that you should use for IOMMUs
that sit between DMA devices and kernel memory. The idea is that you
completely abstract the concept of an IOMMU so the device driver uses
the same code for talking to a device with an IOMMU and another device with
a linear mapping or an swiotlb bounce buffer.
This means that the user of the dma-mapping API does not get to choose the
bus addresses, but instead you use the API to get a bus address for a
chunk of memory, and then you can pass that address to a device.
See arch/powerpc/kernel/iommu.c and arch/x86/kernel/amd_iommu.c for common
examples of how this is implemented. The latter one actually implements
both the iommu_ops for iommu.h and dma_map_ops for dma-mapping.h.
Arnd
^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH 3/7] ARM: Samsung: update/rewrite Samsung SYSMMU (IOMMU) driver
2011-03-11 11:50 ` Arnd Bergmann
@ 2011-03-11 12:35 ` Marek Szyprowski
2011-03-11 14:07 ` Arnd Bergmann
0 siblings, 1 reply; 29+ messages in thread
From: Marek Szyprowski @ 2011-03-11 12:35 UTC (permalink / raw)
To: linux-arm-kernel
Hello,
On Friday, March 11, 2011 12:51 PM Arnd Bergmann wrote:
> On Friday 11 March 2011, Marek Szyprowski wrote:
> >
> > We followed the style of iommu API for other mainline ARM platforms (both OMAP and MSM
> > also have custom API for their iommu modules). I've briefly checked include/linux/iommu.h
> > API and I've noticed that it has been designed mainly for KVM support. There is also
> > include/linux/intel-iommu.h interface, but I it is very specific to intel gfx chips.
>
> The MSM code actually uses the generic iommu.h code, using register_iommu, so
> the drivers can use the regular iommu_map.
>
> I believe the omap code predates the iommu API, and should really be changed
> to use that. At least it was added before I started reviewing the code.
>
> The iommu API is not really meant to be KVM specific, it's just that the
> in-tree users are basically limited to KVM at the moment. Another user that
> is coming up soon is the vmio device driver that can be used to transparently
> pass devices to user space. The idea behind the IOMMU API is that you can
> map arbitrary bus addresses to physical memory addresses, but it does not
> deal with allocating the bus addresses or providing buffer management such
> as cache flushes.
Yea, I've noticed this and this basically what we expect from iommu driver.
However the iommu.h API requires a separate call to map each single memory page.
This is quite ineffective approach and imho the API need to be extended to allow
mapping of the arbitrary set of pages.
> > Is there any example how include/linux/dma-mapping.h interface can be used for iommu
> > mappings?
>
> The dma-mapping API is the normal interface that you should use for IOMMUs
> that sit between DMA devices and kernel memory. The idea is that you
> completely abstract the concept of an IOMMU so the device driver uses
> the same code for talking to a device with an IOMMU and another device with
> a linear mapping or an swiotlb bounce buffer.
>
> This means that the user of the dma-mapping API does not get to choose the
> bus addresses, but instead you use the API to get a bus address for a
> chunk of memory, and then you can pass that address to a device.
>
> See arch/powerpc/kernel/iommu.c and arch/x86/kernel/amd_iommu.c for common
> examples of how this is implemented. The latter one actually implements
> both the iommu_ops for iommu.h and dma_map_ops for dma-mapping.h.
Thanks for your comments! We will check how is it suitable for our case.
Best regards
--
Marek Szyprowski
Samsung Poland R&D Center
^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH 3/7] ARM: Samsung: update/rewrite Samsung SYSMMU (IOMMU) driver
2011-03-11 12:35 ` Marek Szyprowski
@ 2011-03-11 14:07 ` Arnd Bergmann
2011-03-11 14:51 ` Marek Szyprowski
0 siblings, 1 reply; 29+ messages in thread
From: Arnd Bergmann @ 2011-03-11 14:07 UTC (permalink / raw)
To: linux-arm-kernel
On Friday 11 March 2011, Marek Szyprowski wrote:
> > The iommu API is not really meant to be KVM specific, it's just that the
> > in-tree users are basically limited to KVM at the moment. Another user that
> > is coming up soon is the vmio device driver that can be used to transparently
> > pass devices to user space. The idea behind the IOMMU API is that you can
> > map arbitrary bus addresses to physical memory addresses, but it does not
> > deal with allocating the bus addresses or providing buffer management such
> > as cache flushes.
>
> Yea, I've noticed this and this basically what we expect from iommu driver.
> However the iommu.h API requires a separate call to map each single memory page.
> This is quite ineffective approach and imho the API need to be extended to allow
> mapping of the arbitrary set of pages.
We can always discuss extensions to the existing infrastructure, adding
an interface for mapping an array of page pointers in the iommu API
sounds like a good idea.
I also think that we should not really have separate iommu and dma-mapping
interfaces, but rather have a portable way to define an iommu so that it
can be used through the dma-mapping interfaces. I'm not asking you to
do that as a prerequisite to merging your driver, but it may be good to
keep in mind that the current situation is still lacking and that any
suggestion for improving this as part of your work to support the
samsung IOMMU is welcome.
Note that the ARM implementation of the dma-mapping.h interface currently
does not support IOMMUs, but that could be changed by wrapping it
using the include/asm-generic/dma-mapping-common.h infrastructure.
Arnd
^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH 3/7] ARM: Samsung: update/rewrite Samsung SYSMMU (IOMMU) driver
2011-03-11 14:07 ` Arnd Bergmann
@ 2011-03-11 14:51 ` Marek Szyprowski
2011-03-11 15:15 ` Arnd Bergmann
0 siblings, 1 reply; 29+ messages in thread
From: Marek Szyprowski @ 2011-03-11 14:51 UTC (permalink / raw)
To: linux-arm-kernel
Hello,
On Friday, March 11, 2011 3:08 PM Arnd Bergmann wrote:
> On Friday 11 March 2011, Marek Szyprowski wrote:
> > > The iommu API is not really meant to be KVM specific, it's just that the
> > > in-tree users are basically limited to KVM at the moment. Another user that
> > > is coming up soon is the vmio device driver that can be used to transparently
> > > pass devices to user space. The idea behind the IOMMU API is that you can
> > > map arbitrary bus addresses to physical memory addresses, but it does not
> > > deal with allocating the bus addresses or providing buffer management such
> > > as cache flushes.
> >
> > Yea, I've noticed this and this basically what we expect from iommu driver.
> > However the iommu.h API requires a separate call to map each single memory page.
> > This is quite ineffective approach and imho the API need to be extended to allow
> > mapping of the arbitrary set of pages.
>
> We can always discuss extensions to the existing infrastructure, adding
> an interface for mapping an array of page pointers in the iommu API
> sounds like a good idea.
We will investigate this API further. From the first sight it looks it won't take
much work to port/rewrite our driver to fit into iommu.h API.
> I also think that we should not really have separate iommu and dma-mapping
> interfaces, but rather have a portable way to define an iommu so that it
> can be used through the dma-mapping interfaces. I'm not asking you to
> do that as a prerequisite to merging your driver, but it may be good to
> keep in mind that the current situation is still lacking and that any
> suggestion for improving this as part of your work to support the
> samsung IOMMU is welcome.
Well creating a portable iommu framework and merging it with dma-mapping interface
looks like a much harder (and time consuming) task. There is definitely a need for
it. I hope that it can be developed incrementally starting from the current iommu.h
and dma-mapping.h interfaces. Please note that there might be some subtle differences
in the hardware that such framework must be aware. The first obvious one is the
hardware design. Some platform has central iommu unit, other (like Samsung Exynos4)
has a separate iommu unit per each device driver (this is still a simplification,
because a video codec device has 2 memory interfaces and 2 iommu units). Currently
I probably have not enough knowledge to predict the other possible issues that need
to be taken into account in the portable and generic iommu/dma-mapping frame-work.
> Note that the ARM implementation of the dma-mapping.h interface currently
> does not support IOMMUs, but that could be changed by wrapping it
> using the include/asm-generic/dma-mapping-common.h infrastructure.
ARM dma-mapping framework also requires some additional research for better DMA
support (there are still issues with multiple mappings to be resolved).
Best regards
--
Marek Szyprowski
Samsung Poland R&D Center
^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH 3/7] ARM: Samsung: update/rewrite Samsung SYSMMU (IOMMU) driver
2011-03-11 14:51 ` Marek Szyprowski
@ 2011-03-11 15:15 ` Arnd Bergmann
2011-03-11 15:39 ` Marek Szyprowski
0 siblings, 1 reply; 29+ messages in thread
From: Arnd Bergmann @ 2011-03-11 15:15 UTC (permalink / raw)
To: linux-arm-kernel
On Friday 11 March 2011, Marek Szyprowski wrote:
> On Friday, March 11, 2011 3:08 PM Arnd Bergmann wrote:
>
> > On Friday 11 March 2011, Marek Szyprowski wrote:
> > > > The iommu API is not really meant to be KVM specific, it's just that the
> > > > in-tree users are basically limited to KVM at the moment. Another user that
> > > > is coming up soon is the vmio device driver that can be used to transparently
> > > > pass devices to user space. The idea behind the IOMMU API is that you can
> > > > map arbitrary bus addresses to physical memory addresses, but it does not
> > > > deal with allocating the bus addresses or providing buffer management such
> > > > as cache flushes.
> > >
> > > Yea, I've noticed this and this basically what we expect from iommu driver.
> > > However the iommu.h API requires a separate call to map each single memory page.
> > > This is quite ineffective approach and imho the API need to be extended to allow
> > > mapping of the arbitrary set of pages.
> >
> > We can always discuss extensions to the existing infrastructure, adding
> > an interface for mapping an array of page pointers in the iommu API
> > sounds like a good idea.
>
> We will investigate this API further. From the first sight it looks it won't take
> much work to port/rewrite our driver to fit into iommu.h API.
Ok, sounds good.
> > I also think that we should not really have separate iommu and dma-mapping
> > interfaces, but rather have a portable way to define an iommu so that it
> > can be used through the dma-mapping interfaces. I'm not asking you to
> > do that as a prerequisite to merging your driver, but it may be good to
> > keep in mind that the current situation is still lacking and that any
> > suggestion for improving this as part of your work to support the
> > samsung IOMMU is welcome.
>
> Well creating a portable iommu framework and merging it with dma-mapping interface
> looks like a much harder (and time consuming) task. There is definitely a need for
> it. I hope that it can be developed incrementally starting from the current iommu.h
> and dma-mapping.h interfaces.
Yes, that is the idea. Maybe we should add it to the list things that the
Linaro kernel working group can target for the November release?
> Please note that there might be some subtle differences
> in the hardware that such framework must be aware. The first obvious one is the
> hardware design. Some platform has central iommu unit, other (like Samsung Exynos4)
> has a separate iommu unit per each device driver (this is still a simplification,
> because a video codec device has 2 memory interfaces and 2 iommu units). Currently
> I probably have not enough knowledge to predict the other possible issues that need
> to be taken into account in the portable and generic iommu/dma-mapping frame-work.
The dma-mapping API can deal well with one IOMMU per device, but would
need some tricks to work with one device that has two separate IOMMUs.
I'm not very familar with the iommu API, but in the common KVM scenario,
you need one IOMMU per device, so it should handle that just fine as well.
> > Note that the ARM implementation of the dma-mapping.h interface currently
> > does not support IOMMUs, but that could be changed by wrapping it
> > using the include/asm-generic/dma-mapping-common.h infrastructure.
>
> ARM dma-mapping framework also requires some additional research for better DMA
> support (there are still issues with multiple mappings to be resolved).
You mean mapping the same memory into multiple devices, or a different problem?
Arnd
^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH 3/7] ARM: Samsung: update/rewrite Samsung SYSMMU (IOMMU) driver
2011-03-11 15:15 ` Arnd Bergmann
@ 2011-03-11 15:39 ` Marek Szyprowski
2011-03-11 16:00 ` Arnd Bergmann
0 siblings, 1 reply; 29+ messages in thread
From: Marek Szyprowski @ 2011-03-11 15:39 UTC (permalink / raw)
To: linux-arm-kernel
Hello,
On Friday, March 11, 2011 4:15 PM Arnd Bergmann wrote:
> On Friday 11 March 2011, Marek Szyprowski wrote:
> > On Friday, March 11, 2011 3:08 PM Arnd Bergmann wrote:
> >
> > > On Friday 11 March 2011, Marek Szyprowski wrote:
> > > > > The iommu API is not really meant to be KVM specific, it's just that the
> > > > > in-tree users are basically limited to KVM at the moment. Another user that
> > > > > is coming up soon is the vmio device driver that can be used to transparently
> > > > > pass devices to user space. The idea behind the IOMMU API is that you can
> > > > > map arbitrary bus addresses to physical memory addresses, but it does not
> > > > > deal with allocating the bus addresses or providing buffer management such
> > > > > as cache flushes.
> > > >
> > > > Yea, I've noticed this and this basically what we expect from iommu driver.
> > > > However the iommu.h API requires a separate call to map each single memory page.
> > > > This is quite ineffective approach and imho the API need to be extended to allow
> > > > mapping of the arbitrary set of pages.
> > >
> > > We can always discuss extensions to the existing infrastructure, adding
> > > an interface for mapping an array of page pointers in the iommu API
> > > sounds like a good idea.
> >
> > We will investigate this API further. From the first sight it looks it won't take
> > much work to port/rewrite our driver to fit into iommu.h API.
>
> Ok, sounds good.
>
> > > I also think that we should not really have separate iommu and dma-mapping
> > > interfaces, but rather have a portable way to define an iommu so that it
> > > can be used through the dma-mapping interfaces. I'm not asking you to
> > > do that as a prerequisite to merging your driver, but it may be good to
> > > keep in mind that the current situation is still lacking and that any
> > > suggestion for improving this as part of your work to support the
> > > samsung IOMMU is welcome.
> >
> > Well creating a portable iommu framework and merging it with dma-mapping interface
> > looks like a much harder (and time consuming) task. There is definitely a need for
> > it. I hope that it can be developed incrementally starting from the current iommu.h
> > and dma-mapping.h interfaces.
>
> Yes, that is the idea. Maybe we should add it to the list things that the
> Linaro kernel working group can target for the November release?
>
> > Please note that there might be some subtle differences
> > in the hardware that such framework must be aware. The first obvious one is the
> > hardware design. Some platform has central iommu unit, other (like Samsung Exynos4)
> > has a separate iommu unit per each device driver (this is still a simplification,
> > because a video codec device has 2 memory interfaces and 2 iommu units). Currently
> > I probably have not enough knowledge to predict the other possible issues that need
> > to be taken into account in the portable and generic iommu/dma-mapping frame-work.
>
> The dma-mapping API can deal well with one IOMMU per device, but would
> need some tricks to work with one device that has two separate IOMMUs.
We need to investigate the internals of dma-mapping API first. Right now I know too
little in this area.
> I'm not very familar with the iommu API, but in the common KVM scenario,
> you need one IOMMU per device, so it should handle that just fine as well.
Well, afair there are also systems with one central iommu module, which is shared
between devices. I have no idea how such model will fit into the dma-mapping API.
> > > Note that the ARM implementation of the dma-mapping.h interface currently
> > > does not support IOMMUs, but that could be changed by wrapping it
> > > using the include/asm-generic/dma-mapping-common.h infrastructure.
> >
> > ARM dma-mapping framework also requires some additional research for better DMA
> > support (there are still issues with multiple mappings to be resolved).
>
> You mean mapping the same memory into multiple devices, or a different problem?
Mapping the same memory area multiple times with different cache settings is not
legal on ARMv7+ systems. Currently the problems might caused by the low-memory
kernel linear mapping and second mapping created for example by dma_alloc_coherent()
function.
Best regards
--
Marek Szyprowski
Samsung Poland R&D Center
^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH 3/7] ARM: Samsung: update/rewrite Samsung SYSMMU (IOMMU) driver
2011-03-11 15:39 ` Marek Szyprowski
@ 2011-03-11 16:00 ` Arnd Bergmann
2011-03-14 12:37 ` KyongHo Cho
0 siblings, 1 reply; 29+ messages in thread
From: Arnd Bergmann @ 2011-03-11 16:00 UTC (permalink / raw)
To: linux-arm-kernel
On Friday 11 March 2011, Marek Szyprowski wrote:
> > > > does not support IOMMUs, but that could be changed by wrapping it
> > > > using the include/asm-generic/dma-mapping-common.h infrastructure.
> > >
> > > ARM dma-mapping framework also requires some additional research for better DMA
> > > support (there are still issues with multiple mappings to be resolved).
> >
> > You mean mapping the same memory into multiple devices, or a different problem?
>
> Mapping the same memory area multiple times with different cache settings is not
> legal on ARMv7+ systems. Currently the problems might caused by the low-memory
> kernel linear mapping and second mapping created for example by dma_alloc_coherent()
> function.
Yes, I know this problem, but I don't think the case you describe is a serious
limitation (there are more interesting cases, though): dma_map_single() etc
will create additional *bus* addresses for a physical address, not additional
virtual addresses.
dma_alloc_coherent should allocate memory that is not also mapped cached,
which is what I thought we do correctly.
Arnd
^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH 1/7] ARM: S5PV310: Add platform definitions for FIMC
2011-03-04 9:01 ` [PATCH 1/7] ARM: S5PV310: Add platform definitions for FIMC Marek Szyprowski
@ 2011-03-12 0:27 ` Kukjin Kim
0 siblings, 0 replies; 29+ messages in thread
From: Kukjin Kim @ 2011-03-12 0:27 UTC (permalink / raw)
To: linux-arm-kernel
Marek Szyprowski wrote:
>
> From: Sylwester Nawrocki <s.nawrocki@samsung.com>
>
> Add support for fourth FIMC platform device definition and define
> resources for FIMC modules on S5PV310 machines.
>
> Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
> ---
> arch/arm/mach-s5pv310/cpu.c | 7 ++++
> arch/arm/mach-s5pv310/include/mach/irqs.h | 4 ++
> arch/arm/mach-s5pv310/include/mach/map.h | 8 ++++
> arch/arm/plat-s5p/Kconfig | 5 +++
> arch/arm/plat-s5p/Makefile | 1 +
> arch/arm/plat-s5p/dev-fimc3.c | 43
> ++++++++++++++++++++++++
> arch/arm/plat-samsung/include/plat/devs.h | 1 +
> arch/arm/plat-samsung/include/plat/fimc-core.h | 5 +++
> 8 files changed, 74 insertions(+), 0 deletions(-)
> create mode 100644 arch/arm/plat-s5p/dev-fimc3.c
>
> diff --git a/arch/arm/mach-s5pv310/cpu.c b/arch/arm/mach-s5pv310/cpu.c
> index 0db0fb6..0bdb0b0 100644
> --- a/arch/arm/mach-s5pv310/cpu.c
> +++ b/arch/arm/mach-s5pv310/cpu.c
> @@ -21,6 +21,8 @@
> #include <plat/clock.h>
> #include <plat/s5pv310.h>
> #include <plat/sdhci.h>
> +#include <plat/devs.h>
> +#include <plat/fimc-core.h>
>
> #include <mach/regs-irq.h>
>
> @@ -114,6 +116,11 @@ void __init s5pv310_map_io(void)
> s5pv310_default_sdhci1();
> s5pv310_default_sdhci2();
> s5pv310_default_sdhci3();
> +
> + s3c_fimc_setname(0, "s5pv310-fimc");
> + s3c_fimc_setname(1, "s5pv310-fimc");
> + s3c_fimc_setname(2, "s5pv310-fimc");
> + s3c_fimc_setname(3, "s5pv310-fimc");
> }
>
> void __init s5pv310_init_clocks(int xtal)
> diff --git a/arch/arm/mach-s5pv310/include/mach/irqs.h b/arch/arm/mach-
> s5pv310/include/mach/irqs.h
> index 536b0b5..0e99968 100644
> --- a/arch/arm/mach-s5pv310/include/mach/irqs.h
> +++ b/arch/arm/mach-s5pv310/include/mach/irqs.h
> @@ -107,6 +107,10 @@
>
> #define IRQ_MIPI_CSIS0 COMBINER_IRQ(30, 0)
> #define IRQ_MIPI_CSIS1 COMBINER_IRQ(30, 1)
> +#define IRQ_FIMC0 COMBINER_IRQ(32, 0)
> +#define IRQ_FIMC1 COMBINER_IRQ(32, 1)
> +#define IRQ_FIMC2 COMBINER_IRQ(33, 0)
> +#define IRQ_FIMC3 COMBINER_IRQ(33, 1)
>
> #define IRQ_ONENAND_AUDI COMBINER_IRQ(34, 0)
>
> diff --git a/arch/arm/mach-s5pv310/include/mach/map.h b/arch/arm/mach-
> s5pv310/include/mach/map.h
> index 901657f..0db3a47 100644
> --- a/arch/arm/mach-s5pv310/include/mach/map.h
> +++ b/arch/arm/mach-s5pv310/include/mach/map.h
> @@ -25,6 +25,10 @@
>
> #define S5PV310_PA_SYSRAM 0x02025000
>
> +#define S5PV310_PA_FIMC0 0x11800000
> +#define S5PV310_PA_FIMC1 0x11810000
> +#define S5PV310_PA_FIMC2 0x11820000
> +#define S5PV310_PA_FIMC3 0x11830000
> #define S5PV310_PA_I2S0 0x03830000
> #define S5PV310_PA_I2S1 0xE3100000
> #define S5PV310_PA_I2S2 0xE2A00000
> @@ -121,6 +125,10 @@
> #define S5P_PA_CHIPID S5PV310_PA_CHIPID
> #define S5P_PA_MIPI_CSIS0 S5PV310_PA_MIPI_CSIS0
> #define S5P_PA_MIPI_CSIS1 S5PV310_PA_MIPI_CSIS1
> +#define S5P_PA_FIMC0 S5PV310_PA_FIMC0
> +#define S5P_PA_FIMC1 S5PV310_PA_FIMC1
> +#define S5P_PA_FIMC2 S5PV310_PA_FIMC2
> +#define S5P_PA_FIMC3 S5PV310_PA_FIMC3
> #define S5P_PA_ONENAND S5PC210_PA_ONENAND
> #define S5P_PA_ONENAND_DMA S5PC210_PA_ONENAND_DMA
> #define S5P_PA_SDRAM S5PV310_PA_SDRAM
> diff --git a/arch/arm/plat-s5p/Kconfig b/arch/arm/plat-s5p/Kconfig
> index 557f8c5..0db2a7a 100644
> --- a/arch/arm/plat-s5p/Kconfig
> +++ b/arch/arm/plat-s5p/Kconfig
> @@ -60,6 +60,11 @@ config S5P_DEV_FIMC2
> help
> Compile in platform device definitions for FIMC controller 2
>
> +config S5P_DEV_FIMC3
> + bool
> + help
> + Compile in platform device definitions for FIMC controller 3
> +
> config S5P_DEV_ONENAND
> bool
> help
> diff --git a/arch/arm/plat-s5p/Makefile b/arch/arm/plat-s5p/Makefile
> index ce5a0a7..cfcd1db 100644
> --- a/arch/arm/plat-s5p/Makefile
> +++ b/arch/arm/plat-s5p/Makefile
> @@ -28,6 +28,7 @@ obj-$(CONFIG_SUSPEND) += irq-pm.o
> obj-$(CONFIG_S5P_DEV_FIMC0) += dev-fimc0.o
> obj-$(CONFIG_S5P_DEV_FIMC1) += dev-fimc1.o
> obj-$(CONFIG_S5P_DEV_FIMC2) += dev-fimc2.o
> +obj-$(CONFIG_S5P_DEV_FIMC3) += dev-fimc3.o
> obj-$(CONFIG_S5P_DEV_ONENAND) += dev-onenand.o
> obj-$(CONFIG_S5P_DEV_CSIS0) += dev-csis0.o
> obj-$(CONFIG_S5P_DEV_CSIS1) += dev-csis1.o
> diff --git a/arch/arm/plat-s5p/dev-fimc3.c b/arch/arm/plat-s5p/dev-fimc3.c
> new file mode 100644
> index 0000000..ef31bec
> --- /dev/null
> +++ b/arch/arm/plat-s5p/dev-fimc3.c
> @@ -0,0 +1,43 @@
> +/* linux/arch/arm/plat-s5p/dev-fimc3.c
> + *
> + * Copyright (c) 2010 Samsung Electronics
> + *
> + * Base S5P FIMC3 resource and device definitions
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/platform_device.h>
> +#include <linux/interrupt.h>
> +#include <linux/ioport.h>
> +#include <mach/map.h>
> +
> +static struct resource s5p_fimc3_resource[] = {
> + [0] = {
> + .start = S5P_PA_FIMC3,
> + .end = S5P_PA_FIMC3 + SZ_4K - 1,
> + .flags = IORESOURCE_MEM,
> + },
> + [1] = {
> + .start = IRQ_FIMC3,
> + .end = IRQ_FIMC3,
> + .flags = IORESOURCE_IRQ,
> + },
> +};
> +
> +static u64 s5p_fimc3_dma_mask = DMA_BIT_MASK(32);
> +
> +struct platform_device s5p_device_fimc3 = {
> + .name = "s5p-fimc",
> + .id = 3,
> + .num_resources = ARRAY_SIZE(s5p_fimc3_resource),
> + .resource = s5p_fimc3_resource,
> + .dev = {
> + .dma_mask = &s5p_fimc3_dma_mask,
> + .coherent_dma_mask = DMA_BIT_MASK(32),
> + },
> +};
> diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-
> samsung/include/plat/devs.h
> index b4d208b..b0123f3 100644
> --- a/arch/arm/plat-samsung/include/plat/devs.h
> +++ b/arch/arm/plat-samsung/include/plat/devs.h
> @@ -133,6 +133,7 @@ extern struct platform_device samsung_device_keypad;
> extern struct platform_device s5p_device_fimc0;
> extern struct platform_device s5p_device_fimc1;
> extern struct platform_device s5p_device_fimc2;
> +extern struct platform_device s5p_device_fimc3;
>
> extern struct platform_device s5p_device_mipi_csis0;
> extern struct platform_device s5p_device_mipi_csis1;
> diff --git a/arch/arm/plat-samsung/include/plat/fimc-core.h
b/arch/arm/plat-
> samsung/include/plat/fimc-core.h
> index 81a3bfe..945a99d 100644
> --- a/arch/arm/plat-samsung/include/plat/fimc-core.h
> +++ b/arch/arm/plat-samsung/include/plat/fimc-core.h
> @@ -38,6 +38,11 @@ static inline void s3c_fimc_setname(int id, char *name)
> s5p_device_fimc2.name = name;
> break;
> #endif
> +#ifdef CONFIG_S5P_DEV_FIMC3
> + case 3:
> + s5p_device_fimc3.name = name;
> + break;
> +#endif
> }
> }
>
> --
Ok, applied this based on my for-next.
Thanks.
Best regards,
Kgene.
--
Kukjin Kim <kgene.kim@samsung.com>, Senior Engineer,
SW Solution Development Team, Samsung Electronics Co., Ltd.
^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH 3/7] ARM: Samsung: update/rewrite Samsung SYSMMU (IOMMU) driver
2011-03-11 16:00 ` Arnd Bergmann
@ 2011-03-14 12:37 ` KyongHo Cho
2011-03-14 12:46 ` Russell King - ARM Linux
2011-03-14 13:32 ` Arnd Bergmann
0 siblings, 2 replies; 29+ messages in thread
From: KyongHo Cho @ 2011-03-14 12:37 UTC (permalink / raw)
To: linux-arm-kernel
2011/3/12 Arnd Bergmann <arnd@arndb.de>:
> On Friday 11 March 2011, Marek Szyprowski wrote:
>> > > > does not support IOMMUs, but that could be changed by wrapping it
>> > > > using the include/asm-generic/dma-mapping-common.h infrastructure.
>> > >
>> > > ARM dma-mapping framework also requires some additional research for better DMA
>> > > support (there are still issues with multiple mappings to be resolved).
>> >
>> > You mean mapping the same memory into multiple devices, or a different problem?
>>
>> Mapping the same memory area multiple times with different cache settings is not
>> legal on ARMv7+ systems. Currently the problems might caused by the low-memory
>> kernel linear mapping and second mapping created for example by dma_alloc_coherent()
>> function.
>
> Yes, I know this problem, but I don't think the case you describe is a serious
> limitation (there are more interesting cases, though): dma_map_single() etc
> will create additional *bus* addresses for a physical address, not additional
> virtual addresses.
>
> dma_alloc_coherent should allocate memory that is not also mapped cached,
> which is what I thought we do correctly.
I have also noticed that dma_map_single/page/sg() can map physical
memory into an arbitrary device address region.
But it is not enough solution for various kinds of IOMMUs.
As Kukjin Kim addressed, we need to support larger page size than 4KB
because we can reduce TLB miss when we have larger page size.
Our IOMMU(system mmu) supports all page size of ARM architecture
including 16MB, 1MB, 64KB and 4KB.
Since the largest size supported by buddy system of 32-bit architecture is 4MB,
our system support all page sizes except 16MB.
We proved that larger page size is helpful for DMA performance
significantly (more than 10%, approximately).
Big page size is not a problem for peripheral devices
because their address space is not suffer from external fragmentation.
Thanks to Arnd, I never knew about include/linux/iommu.h
Similar to dma-mappings.h, however, It is not enough for our
requirements even though it allows private data to be stored in
iommu_domain for platform-specific requirements.
I think we can consider another solution for the various requirements.
I think one of the most possible solutions is VCMM.
Or we can enhance include/linux/iommu.h with reference of VCMM.
You can find the most recent VCMM submitted at
http://marc.info/?l=linux-kernel&m=129255948319341&w=2
It looks somewhat complex but includes most of required features for
various IOMMUs
which will not be easily solved by include/linux/iommu.h
You can find VCMM core in
http://git.kernel.org/?p=linux/kernel/git/kki_ap/linux-2.6-samsung.git;a=blob;f=mm/vcm.c;h=9fff0106ec0078fad1488308305c8486adbed9c0;hb=refs/heads/2.6.36-samsung
and platform specific implementation of VCMM in
http://git.kernel.org/?p=linux/kernel/git/kki_ap/linux-2.6-samsung.git;a=blob;f=arch/arm/plat-s5p/s5p-vcm.c;h=7498c800aef8b01082e1b1c3ea0f66cefe3c85a1;hb=refs/heads/2.6.36-samsung
Cho KyongHo.
^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH 3/7] ARM: Samsung: update/rewrite Samsung SYSMMU (IOMMU) driver
2011-03-14 12:37 ` KyongHo Cho
@ 2011-03-14 12:46 ` Russell King - ARM Linux
2011-03-15 1:45 ` InKi Dae
2011-03-14 13:32 ` Arnd Bergmann
1 sibling, 1 reply; 29+ messages in thread
From: Russell King - ARM Linux @ 2011-03-14 12:46 UTC (permalink / raw)
To: linux-arm-kernel
On Mon, Mar 14, 2011 at 09:37:51PM +0900, KyongHo Cho wrote:
> I have also noticed that dma_map_single/page/sg() can map physical
> memory into an arbitrary device address region.
> But it is not enough solution for various kinds of IOMMUs.
> As Kukjin Kim addressed, we need to support larger page size than 4KB
> because we can reduce TLB miss when we have larger page size.
>
> Our IOMMU(system mmu) supports all page size of ARM architecture
> including 16MB, 1MB, 64KB and 4KB.
> Since the largest size supported by buddy system of 32-bit architecture is 4MB,
> our system support all page sizes except 16MB.
> We proved that larger page size is helpful for DMA performance
> significantly (more than 10%, approximately).
> Big page size is not a problem for peripheral devices
> because their address space is not suffer from external fragmentation.
1. dma_map_single() et.al. is used for mapping *system* *RAM* for devices
using whatever is necessary. It must not be used for trying to setup
arbitary other mappings.
2. It doesn't matter where the memory for dma_map_single() et.al. comes
from provided the virtual address is a valid system RAM address or
the struct page * is a valid struct page in the memory map (iow, you
can't create this yourself.)
3. In the case of an IOMMU, the DMA API does not limit you to only using
4K pages to setup the IOMMU mappings. You can use whatever you like
provided the hardware can cope with it. You can coalesce several
existing entries together provided you track what you're doing and can
undo what's been done when the mapping is no longer required.
So really there's no reason not to use 64K, 1M and 16M IOMMU entries if
that's the size of buffer which has been passed to the DMA API.
^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH 3/7] ARM: Samsung: update/rewrite Samsung SYSMMU (IOMMU) driver
2011-03-14 12:37 ` KyongHo Cho
2011-03-14 12:46 ` Russell King - ARM Linux
@ 2011-03-14 13:32 ` Arnd Bergmann
1 sibling, 0 replies; 29+ messages in thread
From: Arnd Bergmann @ 2011-03-14 13:32 UTC (permalink / raw)
To: linux-arm-kernel
On Monday 14 March 2011, KyongHo Cho wrote:
> I think we can consider another solution for the various requirements.
> I think one of the most possible solutions is VCMM.
> Or we can enhance include/linux/iommu.h with reference of VCMM.
I think extending or changing the existing interface would be much
preferred. It's always better to limit the number of interfaces
that do the same thing, and we already have more duplication than
we want with the two dma-mapping.h and iommu.h interfaces.
Note that any aspect of the existing interface can be changed if
necessary, as long as there is a way to migrate all the existing
users. Since the iommu API is not exported to user space, there
is no requirement to keep it stable.
Arnd
^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH 3/7] ARM: Samsung: update/rewrite Samsung SYSMMU (IOMMU) driver
2011-03-14 12:46 ` Russell King - ARM Linux
@ 2011-03-15 1:45 ` InKi Dae
2011-03-15 8:35 ` Russell King - ARM Linux
0 siblings, 1 reply; 29+ messages in thread
From: InKi Dae @ 2011-03-15 1:45 UTC (permalink / raw)
To: linux-arm-kernel
2011/3/14 Russell King - ARM Linux <linux@arm.linux.org.uk>:
> On Mon, Mar 14, 2011 at 09:37:51PM +0900, KyongHo Cho wrote:
>> I have also noticed that dma_map_single/page/sg() can map physical
>> memory into an arbitrary device address region.
>> But it is not enough solution for various kinds of IOMMUs.
>> As Kukjin Kim addressed, we need to support larger page size than 4KB
>> because we can reduce TLB miss when we have larger page size.
>>
>> Our IOMMU(system mmu) supports all page size of ARM architecture
>> including 16MB, 1MB, 64KB and 4KB.
>> Since the largest size supported by buddy system of 32-bit architecture is 4MB,
>> our system support all page sizes except 16MB.
>> We proved that larger page size is helpful for DMA performance
>> significantly (more than 10%, approximately).
>> Big page size is not a problem for peripheral devices
>> because their address space is not suffer from external fragmentation.
>
> 1. dma_map_single() et.al. is used for mapping *system* *RAM* for devices
> ? using whatever is necessary. ?It must not be used for trying to setup
> ? arbitary other mappings.
>
> 2. It doesn't matter where the memory for dma_map_single() et.al. comes
> ? from provided the virtual address is a valid system RAM address or
> ? the struct page * is a valid struct page in the memory map (iow, you
> ? can't create this yourself.)
You mean that we cannot have arbitrary virtual address mapping for
iommu based device?
actually, we have memory mapping to arbitrary device virtual address
space, not kernel virtual address space.
>
> 3. In the case of an IOMMU, the DMA API does not limit you to only using
> ? 4K pages to setup the IOMMU mappings. ?You can use whatever you like
> ? provided the hardware can cope with it. ?You can coalesce several
> ? existing entries together provided you track what you're doing and can
> ? undo what's been done when the mapping is no longer required.
>
> So really there's no reason not to use 64K, 1M and 16M IOMMU entries if
> that's the size of buffer which has been passed to the DMA API.
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>
^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH 3/7] ARM: Samsung: update/rewrite Samsung SYSMMU (IOMMU) driver
2011-03-15 1:45 ` InKi Dae
@ 2011-03-15 8:35 ` Russell King - ARM Linux
2011-03-15 9:34 ` daeinki
0 siblings, 1 reply; 29+ messages in thread
From: Russell King - ARM Linux @ 2011-03-15 8:35 UTC (permalink / raw)
To: linux-arm-kernel
On Tue, Mar 15, 2011 at 10:45:50AM +0900, InKi Dae wrote:
> 2011/3/14 Russell King - ARM Linux <linux@arm.linux.org.uk>:
> > On Mon, Mar 14, 2011 at 09:37:51PM +0900, KyongHo Cho wrote:
> >> I have also noticed that dma_map_single/page/sg() can map physical
> >> memory into an arbitrary device address region.
> >> But it is not enough solution for various kinds of IOMMUs.
> >> As Kukjin Kim addressed, we need to support larger page size than 4KB
> >> because we can reduce TLB miss when we have larger page size.
> >>
> >> Our IOMMU(system mmu) supports all page size of ARM architecture
> >> including 16MB, 1MB, 64KB and 4KB.
> >> Since the largest size supported by buddy system of 32-bit architecture is 4MB,
> >> our system support all page sizes except 16MB.
> >> We proved that larger page size is helpful for DMA performance
> >> significantly (more than 10%, approximately).
> >> Big page size is not a problem for peripheral devices
> >> because their address space is not suffer from external fragmentation.
> >
> > 1. dma_map_single() et.al. is used for mapping *system* *RAM* for devices
> > ? using whatever is necessary. ?It must not be used for trying to setup
> > ? arbitary other mappings.
> >
> > 2. It doesn't matter where the memory for dma_map_single() et.al. comes
> > ? from provided the virtual address is a valid system RAM address or
> > ? the struct page * is a valid struct page in the memory map (iow, you
> > ? can't create this yourself.)
>
> You mean that we cannot have arbitrary virtual address mapping for
> iommu based device?
No. I mean exactly what I said - I'm talking about the DMA API in the
above two points. The implication is that you can not create arbitary
mappings of non-system RAM with the DMA API.
> actually, we have memory mapping to arbitrary device virtual address
> space, not kernel virtual address space.
>
> >
> > 3. In the case of an IOMMU, the DMA API does not limit you to only using
> > ? 4K pages to setup the IOMMU mappings. ?You can use whatever you like
> > ? provided the hardware can cope with it. ?You can coalesce several
> > ? existing entries together provided you track what you're doing and can
> > ? undo what's been done when the mapping is no longer required.
> >
> > So really there's no reason not to use 64K, 1M and 16M IOMMU entries if
> > that's the size of buffer which has been passed to the DMA API.
> >
> > _______________________________________________
> > linux-arm-kernel mailing list
> > linux-arm-kernel at lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> >
^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH 3/7] ARM: Samsung: update/rewrite Samsung SYSMMU (IOMMU) driver
2011-03-15 8:35 ` Russell King - ARM Linux
@ 2011-03-15 9:34 ` daeinki
2011-03-15 9:53 ` Russell King - ARM Linux
0 siblings, 1 reply; 29+ messages in thread
From: daeinki @ 2011-03-15 9:34 UTC (permalink / raw)
To: linux-arm-kernel
Russell King - ARM Linux ? ?:
> On Tue, Mar 15, 2011 at 10:45:50AM +0900, InKi Dae wrote:
>> 2011/3/14 Russell King - ARM Linux <linux@arm.linux.org.uk>:
>>> On Mon, Mar 14, 2011 at 09:37:51PM +0900, KyongHo Cho wrote:
>>>> I have also noticed that dma_map_single/page/sg() can map physical
>>>> memory into an arbitrary device address region.
>>>> But it is not enough solution for various kinds of IOMMUs.
>>>> As Kukjin Kim addressed, we need to support larger page size than 4KB
>>>> because we can reduce TLB miss when we have larger page size.
>>>>
>>>> Our IOMMU(system mmu) supports all page size of ARM architecture
>>>> including 16MB, 1MB, 64KB and 4KB.
>>>> Since the largest size supported by buddy system of 32-bit architecture is 4MB,
>>>> our system support all page sizes except 16MB.
>>>> We proved that larger page size is helpful for DMA performance
>>>> significantly (more than 10%, approximately).
>>>> Big page size is not a problem for peripheral devices
>>>> because their address space is not suffer from external fragmentation.
>>> 1. dma_map_single() et.al. is used for mapping *system* *RAM* for devices
>>> using whatever is necessary. It must not be used for trying to setup
>>> arbitary other mappings.
>>>
>>> 2. It doesn't matter where the memory for dma_map_single() et.al. comes
>>> from provided the virtual address is a valid system RAM address or
>>> the struct page * is a valid struct page in the memory map (iow, you
>>> can't create this yourself.)
>> You mean that we cannot have arbitrary virtual address mapping for
>> iommu based device?
>
> No. I mean exactly what I said - I'm talking about the DMA API in the
> above two points. The implication is that you can not create arbitary
> mappings of non-system RAM with the DMA API.
>
sorry but I couldn't understand exactly what you said. could you give me
your answer one more time?
does non-system RAM mean reserved memory regions? if not, is it
arbitrary virtual address space that isn't kernel or user virtual
address space and is the space for iommu based deivce?
>> actually, we have memory mapping to arbitrary device virtual address
>> space, not kernel virtual address space.
>>
>>> 3. In the case of an IOMMU, the DMA API does not limit you to only using
>>> 4K pages to setup the IOMMU mappings. You can use whatever you like
>>> provided the hardware can cope with it. You can coalesce several
>>> existing entries together provided you track what you're doing and can
>>> undo what's been done when the mapping is no longer required.
>>>
>>> So really there's no reason not to use 64K, 1M and 16M IOMMU entries if
>>> that's the size of buffer which has been passed to the DMA API.
>>>
>>> _______________________________________________
>>> linux-arm-kernel mailing list
>>> linux-arm-kernel at lists.infradead.org
>>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>>
>
^ permalink raw reply [flat|nested] 29+ messages in thread
* [PATCH 3/7] ARM: Samsung: update/rewrite Samsung SYSMMU (IOMMU) driver
2011-03-15 9:34 ` daeinki
@ 2011-03-15 9:53 ` Russell King - ARM Linux
0 siblings, 0 replies; 29+ messages in thread
From: Russell King - ARM Linux @ 2011-03-15 9:53 UTC (permalink / raw)
To: linux-arm-kernel
On Tue, Mar 15, 2011 at 06:34:42PM +0900, daeinki wrote:
> Russell King - ARM Linux ? ?:
>> On Tue, Mar 15, 2011 at 10:45:50AM +0900, InKi Dae wrote:
>>> 2011/3/14 Russell King - ARM Linux <linux@arm.linux.org.uk>:
>>>> On Mon, Mar 14, 2011 at 09:37:51PM +0900, KyongHo Cho wrote:
>>>>> I have also noticed that dma_map_single/page/sg() can map physical
>>>>> memory into an arbitrary device address region.
>>>>> But it is not enough solution for various kinds of IOMMUs.
>>>>> As Kukjin Kim addressed, we need to support larger page size than 4KB
>>>>> because we can reduce TLB miss when we have larger page size.
>>>>>
>>>>> Our IOMMU(system mmu) supports all page size of ARM architecture
>>>>> including 16MB, 1MB, 64KB and 4KB.
>>>>> Since the largest size supported by buddy system of 32-bit architecture is 4MB,
>>>>> our system support all page sizes except 16MB.
>>>>> We proved that larger page size is helpful for DMA performance
>>>>> significantly (more than 10%, approximately).
>>>>> Big page size is not a problem for peripheral devices
>>>>> because their address space is not suffer from external fragmentation.
>>>> 1. dma_map_single() et.al. is used for mapping *system* *RAM* for devices
>>>> using whatever is necessary. It must not be used for trying to setup
>>>> arbitary other mappings.
>>>>
>>>> 2. It doesn't matter where the memory for dma_map_single() et.al. comes
>>>> from provided the virtual address is a valid system RAM address or
>>>> the struct page * is a valid struct page in the memory map (iow, you
>>>> can't create this yourself.)
>>> You mean that we cannot have arbitrary virtual address mapping for
>>> iommu based device?
>>
>> No. I mean exactly what I said - I'm talking about the DMA API in the
>> above two points. The implication is that you can not create arbitary
>> mappings of non-system RAM with the DMA API.
>>
> sorry but I couldn't understand exactly what you said. could you give me
> your answer one more time?
> does non-system RAM mean reserved memory regions? if not, is it
> arbitrary virtual address space that isn't kernel or user virtual
> address space and is the space for iommu based deivce?
For dma_map_single(dev, addr, size, dir), basically:
for (a = addr; a < addr + size; a += PAGE_SIZE)
BUG_ON(!virt_addr_valid(a));
For dma_map_page(dev, page, offset, size, dir), 'page' must be something
obtained from one of the page-based kernel allocators (so either refering
to a page in the *existing* lowmem or highmem memory) _and_ you must not
use offset/size to then point@something outside that.
So, if you take something out of the kernel's knowledge of what is memory,
you can't then use the DMA API with it.
^ permalink raw reply [flat|nested] 29+ messages in thread
end of thread, other threads:[~2011-03-15 9:53 UTC | newest]
Thread overview: 29+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-03-04 9:01 [PATCH/RFC 0/7] Samsung IOMMU videobuf2 allocator and s5p-fimc update Marek Szyprowski
2011-03-04 9:01 ` [PATCH 1/7] ARM: S5PV310: Add platform definitions for FIMC Marek Szyprowski
2011-03-12 0:27 ` Kukjin Kim
2011-03-04 9:01 ` [PATCH 2/7] ARM: S5PV310: power domains: fixes and code cleanup Marek Szyprowski
2011-03-04 9:01 ` [PATCH 3/7] ARM: Samsung: update/rewrite Samsung SYSMMU (IOMMU) driver Marek Szyprowski
2011-03-04 16:04 ` Marek Szyprowski
2011-03-10 14:52 ` Arnd Bergmann
2011-03-11 9:04 ` Marek Szyprowski
2011-03-11 11:50 ` Arnd Bergmann
2011-03-11 12:35 ` Marek Szyprowski
2011-03-11 14:07 ` Arnd Bergmann
2011-03-11 14:51 ` Marek Szyprowski
2011-03-11 15:15 ` Arnd Bergmann
2011-03-11 15:39 ` Marek Szyprowski
2011-03-11 16:00 ` Arnd Bergmann
2011-03-14 12:37 ` KyongHo Cho
2011-03-14 12:46 ` Russell King - ARM Linux
2011-03-15 1:45 ` InKi Dae
2011-03-15 8:35 ` Russell King - ARM Linux
2011-03-15 9:34 ` daeinki
2011-03-15 9:53 ` Russell King - ARM Linux
2011-03-14 13:32 ` Arnd Bergmann
2011-03-04 9:01 ` [PATCH 4/7] v4l: videobuf2: add Samsung SYSMMU (IOMMU) based allocator Marek Szyprowski
2011-03-04 9:01 ` [PATCH 5/7] s5p-fimc: add pm_runtime support Marek Szyprowski
2011-03-04 9:01 ` [PATCH 6/7] s5p-fimc: Add support for vb2-s5p-iommu allocator Marek Szyprowski
2011-03-04 9:01 ` [PATCH 7/7] ARM: S5PC210: enable FIMC on Universal_C210 Marek Szyprowski
2011-03-08 7:28 ` [PATCH/RFC 0/7] Samsung IOMMU videobuf2 allocator and s5p-fimc update Kukjin Kim
2011-03-08 9:34 ` Marek Szyprowski
2011-03-08 10:05 ` InKi Dae
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).