Skip to contentSkip to conversation

Exynos SYSMMU (IOMMU) integration with DT and DMA-mapping subsystem

PATCH Superseded Marek Szyprowski 7 participants 34 messages Jan 23, 2015 – Apr 17, 2015

Subsystems (8)

v5 of 7 Superseded Latest is v7 →

lore
Share & tools
lore

Marek Szyprowski

author maintainer
#0 lore raw

v5 cover Exynos SYSMMU (IOMMU) integration with DT and DMA-mapping subsystem

Hello Everyone,

This is yet another attempt to get Exynos SYSMMU driver with integrated with IOMMU & DMA-mapping subsystems. The main change from previous version is a rebase onto some more pending Exynos DTS patches and minor fixes of the reported issues.

Merge plan for this patchset:

1. All iommu related patches (with 'iommu: exynos') can be merged to iommu tree. They don't have any direct dependencies on the DTS, DRM and power domain initialization change - without them the driver will simply not initialize, when no exynos,sysmmu nodes are provided in device tree.

Joerg, could you merge those patches?

2. DTS and power domain patches should go to Samsung Exynos tree. Those patches depends on earlier DTS patches for Exynos SoCs, which make this patchset really complete:
- 'ARM: DTS: Exynos: convert to generic power domain bindings'
(http://www.spinics.net/lists/linux-samsung-soc/msg40584.html)
- '[PATCH v4 0/7] Enable HDMI support on Exynos platforms'
(http://www.spinics.net/lists/arm-kernel/msg391148.html)
- '[PATCH 0/2] Add HDMI support for Exynos5420 platform'
(http://www.spinics.net/lists/linux-samsung-soc/msg41364.html)

Kukjin, could you merge those patches?

3. Exynos DRM fix. This patch in my opinion should go Exynos DRM tree.

Inki, could you merge it?

Best regards
Marek Szyprowski
Samsung R&D Institute Poland

Changelog:

v5:
- rebased onto 'Add HDMI support for Exynos5420 platform' patchset
- fixed 'const' issue in 'iommu: exynos: init from dt-specific callback instead of initcall' patch, thanks to Tobias Jakobi for reporting it
- fixed copy-paste typo in exynos5250 dts patch

v4: http://www.spinics.net/lists/linux-samsung-soc/msg41177.html
- rebased onto v3.19-rc4 and other Exynos DTS queued patches
- added DTS patch for Exynos 5250 & 5420/5422/5800

v3: http://www.spinics.net/lists/linux-samsung-soc/msg39168.html
- rebased onto "[RFC PATCH v4 0/8] Introduce automatic DMA configuration for IOMMU masters"
- added some minor fixes for iommu and dma-mapping frameworks

v2: http://thread.gmane.org/gmane.linux.kernel.iommu/6472/
- rebased onto "[RFC PATCH v3 0/7] Introduce automatic DMA configuration for IOMMU masters" patches:
http://www.spinics.net/lists/arm-kernel/msg362076.html
- changed initialization from bus notifiers to DT related callbacks
- removed support for separate IO address spaces - this will be discussed separately after the basic support gets merged
- removed support for power domain notifier-based runtime power management - this also will be discussed separately later

v1: https://lkml.org/lkml/2014/8/5/183
- initial version, feature complete, completely rewrote integration approach

Patch summary:

Marek Szyprowski (18):
drm: exynos: detach from default dma-mapping domain on init
arm: exynos: pm_domains: add support for devices registered before
arch_initcall
ARM: dts: exynos4: add sysmmu nodes
ARM: dts: exynos5250: add sysmmu nodes
ARM: dts: exynos5420: add sysmmu nodes
iommu: exynos: don't read version register on every tlb operation
iommu: exynos: remove unused functions
iommu: exynos: remove useless spinlock
iommu: exynos: refactor function parameters to simplify code
iommu: exynos: remove unused functions, part 2
iommu: exynos: remove useless device_add/remove callbacks
iommu: exynos: add support for binding more than one sysmmu to master
device
iommu: exynos: add support for runtime_pm
iommu: exynos: rename variables to reflect their purpose
iommu: exynos: document internal structures
iommu: exynos: remove excessive includes and sort others
alphabetically
iommu: exynos: init from dt-specific callback instead of initcall
iommu: exynos: add callback for initializing devices from device tree

 arch/arm/boot/dts/exynos4.dtsi            | 118 +++++++
 arch/arm/boot/dts/exynos4210.dtsi         |  23 ++
 arch/arm/boot/dts/exynos4x12.dtsi         |  82 +++++
 arch/arm/boot/dts/exynos5250.dtsi         | 250 +++++++++++++++
 arch/arm/boot/dts/exynos5420.dtsi         | 181 +++++++++++
 arch/arm/mach-exynos/pm_domains.c         |   9 +-
 drivers/gpu/drm/exynos/exynos_drm_iommu.c |   3 +
 drivers/iommu/exynos-iommu.c              | 492 ++++++++++++++----------------
 8 files changed, 888 insertions(+), 270 deletions(-)
Signature · 1 line
1.9.2
author maintainer
#1 lore raw

PATCH v5 1/18 drm: exynos: detach from default dma-mapping domain on init

This patch adds code, which detach sub-device nodes from default iommu domain if such has been configured.

---
 drivers/gpu/drm/exynos/exynos_drm_iommu.c | 3 +++
 1 file changed, 3 insertions(+)
drivers/gpu/drm/exynos/exynos_drm_iommu.c +3 -0
index b32b291..323601a 100644
@@ -100,6 +100,9 @@ int drm_iommu_attach_device(struct drm_device *drm_dev,
 
 	dma_set_max_seg_size(subdrv_dev, 0xffffffffu);
 
+	if (subdrv_dev->archdata.mapping)
+		arm_iommu_detach_device(subdrv_dev);
+
 	ret = arm_iommu_attach_device(subdrv_dev, dev->archdata.mapping);
 	if (ret < 0) {
 		DRM_DEBUG_KMS("failed iommu attach.\n");
Signature · 1 line
1.9.2
author maintainer
#2 lore raw

PATCH v5 2/18 arm: exynos: pm_domains: add support for devices registered before arch_initcall

In reply to Marek Szyprowski

SYSMMU devices will be registered early before any other devices and before calling arch_initcall. To add them to respective power domains, additional scan of all platform devices is needed.

---
 arch/arm/mach-exynos/pm_domains.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)
arch/arm/mach-exynos/pm_domains.c +8 -1
index 37266a8..0e2bc36 100644
@@ -105,6 +105,12 @@ static int exynos_pd_power_off(struct generic_pm_domain *domain)
 	return exynos_pd_power(domain, false);
 }
 
+static __init int exynos_pd_init_platform_dev(struct device *dev, void *data)
+{
+	dev_pm_domain_attach(dev, true);
+	return 0;
+}
+
 static __init int exynos4_pm_init_power_domain(void)
 {
 	struct platform_device *pdev;
@@ -189,6 +195,7 @@ no_clk:
 		of_node_put(np);
 	}
 
-	return 0;
+	return bus_for_each_dev(&platform_bus_type, NULL, NULL,
+				exynos_pd_init_platform_dev);
 }
 arch_initcall(exynos4_pm_init_power_domain);
Signature · 1 line
1.9.2
author maintainer
#3 lore raw

PATCH v5 3/18 ARM: dts: exynos4: add sysmmu nodes

In reply to Marek Szyprowski

This patch adds System MMU nodes that are specific to Exynos4210/4x12 series.

---
 arch/arm/boot/dts/exynos4.dtsi    | 118 ++++++++++++++++++++++++++++++++++++++
 arch/arm/boot/dts/exynos4210.dtsi |  23 ++++++++
 arch/arm/boot/dts/exynos4x12.dtsi |  82 ++++++++++++++++++++++++++
 3 files changed, 223 insertions(+)
arch/arm/boot/dts/exynos4.dtsi +118 -0
index a59b3fae..ca219ed 100644
@@ -183,6 +183,7 @@
 			clock-names = "fimc", "sclk_fimc";
 			power-domains = <&pd_cam>;
 			samsung,sysreg = <&sys_reg>;
+			iommus = <&sysmmu_fimc0>;
 			status = "disabled";
 		};
 
@@ -194,6 +195,7 @@
 			clock-names = "fimc", "sclk_fimc";
 			power-domains = <&pd_cam>;
 			samsung,sysreg = <&sys_reg>;
+			iommus = <&sysmmu_fimc1>;
 			status = "disabled";
 		};
 
@@ -205,6 +207,7 @@
 			clock-names = "fimc", "sclk_fimc";
 			power-domains = <&pd_cam>;
 			samsung,sysreg = <&sys_reg>;
+			iommus = <&sysmmu_fimc2>;
 			status = "disabled";
 		};
 
@@ -216,6 +219,7 @@
 			clock-names = "fimc", "sclk_fimc";
 			power-domains = <&pd_cam>;
 			samsung,sysreg = <&sys_reg>;
+			iommus = <&sysmmu_fimc3>;
 			status = "disabled";
 		};
 
@@ -404,6 +408,8 @@
 		clocks = <&clock CLK_MFC>, <&clock CLK_SCLK_MFC>;
 		clock-names = "mfc", "sclk_mfc";
 		status = "disabled";
+		iommus = <&sysmmu_mfc_l>, <&sysmmu_mfc_r>;
+		iommu-names = "left", "right";
 	};
 
 	serial_0: serial at 13800000 {
@@ -669,6 +675,7 @@
 		power-domains = <&pd_lcd0>;
 		samsung,sysreg = <&sys_reg>;
 		status = "disabled";
+		iommus = <&sysmmu_fimd0>;
 	};
 
 	hdmi: hdmi at 12D00000 {
@@ -691,6 +698,117 @@
 		interrupts = <0 91 0>;
 		reg = <0x12C10000 0x2100>, <0x12c00000 0x300>;
 		power-domains = <&pd_tv>;
+		iommus = <&sysmmu_tv>;
 		status = "disabled";
 	};
+
+	sysmmu_mfc_l: sysmmu at 13620000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x13620000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <5 5>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_MFCL>, <&clock CLK_MFC>;
+		power-domains = <&pd_mfc>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_mfc_r: sysmmu at 13630000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x13630000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <5 6>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_MFCR>, <&clock CLK_MFC>;
+		power-domains = <&pd_mfc>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_tv: sysmmu at 12E20000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x12E20000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <5 4>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_TV>, <&clock CLK_MIXER>;
+		power-domains = <&pd_tv>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_fimc0: sysmmu at 11A20000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x11A20000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <4 2>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_FIMC0>, <&clock CLK_FIMC0>;
+		power-domains = <&pd_cam>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_fimc1: sysmmu at 11A30000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x11A30000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <4 3>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_FIMC1>, <&clock CLK_FIMC1>;
+		power-domains = <&pd_cam>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_fimc2: sysmmu at 11A40000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x11A40000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <4 4>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_FIMC2>, <&clock CLK_FIMC2>;
+		power-domains = <&pd_cam>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_fimc3: sysmmu at 11A50000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x11A50000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <4 5>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_FIMC3>, <&clock CLK_FIMC3>;
+		power-domains = <&pd_cam>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_jpeg: sysmmu at 11A60000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x11A60000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <4 6>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_JPEG>, <&clock CLK_JPEG>;
+		power-domains = <&pd_cam>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_rotator: sysmmu at 12A30000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x12A30000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <5 0>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_ROTATOR>, <&clock CLK_ROTATOR>;
+		power-domains = <&pd_lcd0>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_fimd0: sysmmu at 11E20000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x11E20000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <5 2>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_FIMD0>, <&clock CLK_FIMD0>;
+		power-domains = <&pd_lcd0>;
+		#iommu-cells = <0>;
+	};
 };
arch/arm/boot/dts/exynos4210.dtsi +23 -0
index 1b41002..ded9941 100644
@@ -160,6 +160,7 @@
 		interrupts = <0 89 0>;
 		clocks = <&clock CLK_SCLK_FIMG2D>, <&clock CLK_G2D>;
 		clock-names = "sclk_fimg2d", "fimg2d";
+		iommus = <&sysmmu_g2d>;
 		status = "disabled";
 	};
 
@@ -201,4 +202,26 @@
 			<&clock CLK_SCLK_HDMI>, <&clock CLK_VP>,
 			<&clock CLK_MOUT_MIXER>, <&clock CLK_SCLK_MIXER>;
 	};
+
+	sysmmu_g2d: sysmmu at 12A20000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x12A20000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <4 7>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_G2D>, <&clock CLK_G2D>;
+		power-domains = <&pd_lcd0>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_fimd1: sysmmu at 12220000 {
+		compatible = "samsung,exynos-sysmmu";
+		interrupt-parent = <&combiner>;
+		reg = <0x12220000 0x1000>;
+		interrupts = <5 3>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_FIMD1>, <&clock CLK_FIMD1>;
+		power-domains = <&pd_lcd1>;
+		#iommu-cells = <0>;
+	};
 };
arch/arm/boot/dts/exynos4x12.dtsi +82 -0

110 lines not on this page · raw message

Signature · 1 line
1.9.2
author maintainer
#4 lore raw

PATCH v5 4/18 ARM: dts: exynos5250: add sysmmu nodes

In reply to Marek Szyprowski
---
 arch/arm/boot/dts/exynos5250.dtsi | 250 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 250 insertions(+)
arch/arm/boot/dts/exynos5250.dtsi +250 -0
index ae22bd9..8583b9e 100644
@@ -224,6 +224,7 @@
 		interrupts = <0 91 0>;
 		clocks = <&clock CLK_G2D>;
 		clock-names = "fimg2d";
+		iommus = <&sysmmu_g2d>;
 	};
 
 	mfc: codec at 11000000 {
@@ -233,6 +234,8 @@
 		power-domains = <&pd_mfc>;
 		clocks = <&clock CLK_MFC>;
 		clock-names = "mfc";
+		iommus = <&sysmmu_mfc_l>, <&sysmmu_mfc_r>;
+		iommu-names = "left", "right";
 	};
 
 	rtc: rtc at 101E0000 {
@@ -693,6 +696,7 @@
 		power-domains = <&pd_gsc>;
 		clocks = <&clock CLK_GSCL0>;
 		clock-names = "gscl";
+		iommu = <&sysmmu_gsc1>;
 	};
 
 	gsc_1:  gsc at 13e10000 {
@@ -702,6 +706,7 @@
 		power-domains = <&pd_gsc>;
 		clocks = <&clock CLK_GSCL1>;
 		clock-names = "gscl";
+		iommu = <&sysmmu_gsc1>;
 	};
 
 	gsc_2:  gsc at 13e20000 {
@@ -711,6 +716,7 @@
 		power-domains = <&pd_gsc>;
 		clocks = <&clock CLK_GSCL2>;
 		clock-names = "gscl";
+		iommu = <&sysmmu_gsc2>;
 	};
 
 	gsc_3:  gsc at 13e30000 {
@@ -720,6 +726,7 @@
 		power-domains = <&pd_gsc>;
 		clocks = <&clock CLK_GSCL3>;
 		clock-names = "gscl";
+		iommu = <&sysmmu_gsc3>;
 	};
 
 	hdmi: hdmi {
@@ -743,6 +750,7 @@
 		clocks = <&clock CLK_MIXER>, <&clock CLK_HDMI>,
 			 <&clock CLK_SCLK_HDMI>;
 		clock-names = "mixer", "hdmi", "sclk_hdmi";
+		iommus = <&sysmmu_tv>;
 	};
 
 	dp_phy: video-phy at 10040720 {
@@ -763,6 +771,7 @@
 		power-domains = <&pd_disp1>;
 		clocks = <&clock CLK_SCLK_FIMD1>, <&clock CLK_FIMD1>;
 		clock-names = "sclk_fimd", "fimd";
+		iommus = <&sysmmu_fimd1>;
 	};
 
 	adc: adc at 12D10000 {
@@ -784,4 +793,245 @@
 		clocks = <&clock CLK_SSS>;
 		clock-names = "secss";
 	};
+
+	sysmmu_gsc0: sysmmu at 13E80000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x13E80000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <2 0>;
+		power-domains = <&pd_gsc>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_GSCL0>, <&clock CLK_GSCL0>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_gsc1: sysmmu at 13E90000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x13E90000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <2 2>;
+		power-domains = <&pd_gsc>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_GSCL1>, <&clock CLK_GSCL1>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_gsc2: sysmmu at 13EA0000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x13EA0000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <2 4>;
+		power-domains = <&pd_gsc>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_GSCL2>, <&clock CLK_GSCL2>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_gsc3: sysmmu at 13EB0000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x13EB0000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <2 6>;
+		power-domains = <&pd_gsc>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_GSCL3>, <&clock CLK_GSCL3>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_mfc_r: sysmmu at 11200000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x11200000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <6 2>;
+		power-domains = <&pd_mfc>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_MFCR>, <&clock CLK_MFC>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_mfc_l: sysmmu at 11210000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x11210000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <8 5>;
+		power-domains = <&pd_mfc>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_MFCL>, <&clock CLK_MFC>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_tv: sysmmu at 14650000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x14650000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <7 4>;
+		power-domains = <&pd_disp1>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_TV>, <&clock CLK_MIXER>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_fimd1: sysmmu at 14640000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x14640000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <3 2>;
+		power-domains = <&pd_disp1>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_FIMD1>, <&clock CLK_FIMD1>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_g2d: sysmmu at 10A60000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x10A60000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <24 5>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_2D>, <&clock CLK_G2D>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_rotator: sysmmu at 11D40000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x11D40000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <4 0>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_ROTATOR>, <&clock CLK_ROTATOR>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_jpeg: sysmmu at 11F20000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x11F20000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <4 2>;
+		power-domains = <&pd_gsc>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_JPEG>, <&clock CLK_JPEG>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_fimc_isp: sysmmu at 13260000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x13260000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <10 6>;
+		clock-names = "sysmmu";
+		clocks = <&clock CLK_SMMU_FIMC_ISP>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_fimc_drc: sysmmu at 13270000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x13270000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <11 6>;
+		clock-names = "sysmmu";
+		clocks = <&clock CLK_SMMU_FIMC_DRC>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_fimc_fd: sysmmu at 132A0000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x132A0000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <5 0>;
+		clock-names = "sysmmu";
+		clocks = <&clock CLK_SMMU_FIMC_FD>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_fimc_scc: sysmmu at 13280000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x13280000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <5 2>;
+		clock-names = "sysmmu";
+		clocks = <&clock CLK_SMMU_FIMC_SCC>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_fimc_scp: sysmmu at 13290000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x13290000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <3 6>;
+		clock-names = "sysmmu";
+		clocks = <&clock CLK_SMMU_FIMC_SCP>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_fimc_mcuctl: sysmmu at 132B0000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x132B0000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <5 4>;
+		clock-names = "sysmmu";
+		clocks = <&clock CLK_SMMU_FIMC_MCU>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_fimc_odc: sysmmu at 132C0000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x132C0000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <11 0>;
+		clock-names = "sysmmu";
+		clocks = <&clock CLK_SMMU_FIMC_ODC>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_fimc_dis0: sysmmu at 132D0000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x132D0000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <10 4>;
+		clock-names = "sysmmu";
+		clocks = <&clock CLK_SMMU_FIMC_DIS0>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_fimc_dis1: sysmmu at 132E0000{
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x132E0000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <9 4>;
+		clock-names = "sysmmu";
+		clocks = <&clock CLK_SMMU_FIMC_DIS1>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_fimc_3dnr: sysmmu at 132F0000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x132F0000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <5 6>;
+		clock-names = "sysmmu";
+		clocks = <&clock CLK_SMMU_FIMC_3DNR>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_fimc_lite0: sysmmu at 13C40000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x13C40000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <3 4>;
+		power-domains = <&pd_gsc>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_FIMC_LITE0>, <&clock CLK_CAMIF_TOP>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_fimc_lite1: sysmmu at 13C50000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x13C50000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <24 1>;
+		power-domains = <&pd_gsc>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_FIMC_LITE1>, <&clock CLK_CAMIF_TOP>;
+		#iommu-cells = <0>;
+	};
 };
Signature · 1 line
1.9.2
#5 lore raw

PATCH v5 4/18 ARM: dts: exynos5250: add sysmmu nodes

No sysmmu_mdma nodes? when do you plan to add them?

Quoted 327 lines · Marek Szyprowski
---
 arch/arm/boot/dts/exynos5250.dtsi | 250 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 250 insertions(+)
arch/arm/boot/dts/exynos5250.dtsi +250 -1
index ae22bd9..8583b9e 100644
@@ -224,6 +224,7 @@
                interrupts = <0 91 0>;
                clocks = <&clock CLK_G2D>;
                clock-names = "fimg2d";
+               iommus = <&sysmmu_g2d>;
        };
 
        mfc: codec at 11000000 {
@@ -233,6 +234,8 @@
                power-domains = <&pd_mfc>;
                clocks = <&clock CLK_MFC>;
                clock-names = "mfc";
+               iommus = <&sysmmu_mfc_l>, <&sysmmu_mfc_r>;
+               iommu-names = "left", "right";
        };
 
        rtc: rtc at 101E0000 {
@@ -693,6 +696,7 @@
                power-domains = <&pd_gsc>;
                clocks = <&clock CLK_GSCL0>;
                clock-names = "gscl";
+               iommu = <&sysmmu_gsc1>;
        };
 
        gsc_1:  gsc at 13e10000 {
@@ -702,6 +706,7 @@
                power-domains = <&pd_gsc>;
                clocks = <&clock CLK_GSCL1>;
                clock-names = "gscl";
+               iommu = <&sysmmu_gsc1>;
        };
 
        gsc_2:  gsc at 13e20000 {
@@ -711,6 +716,7 @@
                power-domains = <&pd_gsc>;
                clocks = <&clock CLK_GSCL2>;
                clock-names = "gscl";
+               iommu = <&sysmmu_gsc2>;
        };
 
        gsc_3:  gsc at 13e30000 {
@@ -720,6 +726,7 @@
                power-domains = <&pd_gsc>;
                clocks = <&clock CLK_GSCL3>;
                clock-names = "gscl";
+               iommu = <&sysmmu_gsc3>;
        };
 
        hdmi: hdmi {
@@ -743,6 +750,7 @@
                clocks = <&clock CLK_MIXER>, <&clock CLK_HDMI>,
                         <&clock CLK_SCLK_HDMI>;
                clock-names = "mixer", "hdmi", "sclk_hdmi";
+               iommus = <&sysmmu_tv>;
        };
 
        dp_phy: video-phy at 10040720 {
@@ -763,6 +771,7 @@
                power-domains = <&pd_disp1>;
                clocks = <&clock CLK_SCLK_FIMD1>, <&clock CLK_FIMD1>;
                clock-names = "sclk_fimd", "fimd";
+               iommus = <&sysmmu_fimd1>;
        };
 
        adc: adc at 12D10000 {
@@ -784,4 +793,245 @@
                clocks = <&clock CLK_SSS>;
                clock-names = "secss";
        };
+
+       sysmmu_gsc0: sysmmu at 13E80000 {
+               compatible = "samsung,exynos-sysmmu";
+               reg = <0x13E80000 0x1000>;
+               interrupt-parent = <&combiner>;
+               interrupts = <2 0>;
+               power-domains = <&pd_gsc>;
+               clock-names = "sysmmu", "master";
+               clocks = <&clock CLK_SMMU_GSCL0>, <&clock CLK_GSCL0>;
+               #iommu-cells = <0>;
+       };
+
+       sysmmu_gsc1: sysmmu at 13E90000 {
+               compatible = "samsung,exynos-sysmmu";
+               reg = <0x13E90000 0x1000>;
+               interrupt-parent = <&combiner>;
+               interrupts = <2 2>;
+               power-domains = <&pd_gsc>;
+               clock-names = "sysmmu", "master";
+               clocks = <&clock CLK_SMMU_GSCL1>, <&clock CLK_GSCL1>;
+               #iommu-cells = <0>;
+       };
+
+       sysmmu_gsc2: sysmmu at 13EA0000 {
+               compatible = "samsung,exynos-sysmmu";
+               reg = <0x13EA0000 0x1000>;
+               interrupt-parent = <&combiner>;
+               interrupts = <2 4>;
+               power-domains = <&pd_gsc>;
+               clock-names = "sysmmu", "master";
+               clocks = <&clock CLK_SMMU_GSCL2>, <&clock CLK_GSCL2>;
+               #iommu-cells = <0>;
+       };
+
+       sysmmu_gsc3: sysmmu at 13EB0000 {
+               compatible = "samsung,exynos-sysmmu";
+               reg = <0x13EB0000 0x1000>;
+               interrupt-parent = <&combiner>;
+               interrupts = <2 6>;
+               power-domains = <&pd_gsc>;
+               clock-names = "sysmmu", "master";
+               clocks = <&clock CLK_SMMU_GSCL3>, <&clock CLK_GSCL3>;
+               #iommu-cells = <0>;
+       };
+
+       sysmmu_mfc_r: sysmmu at 11200000 {
+               compatible = "samsung,exynos-sysmmu";
+               reg = <0x11200000 0x1000>;
+               interrupt-parent = <&combiner>;
+               interrupts = <6 2>;
+               power-domains = <&pd_mfc>;
+               clock-names = "sysmmu", "master";
+               clocks = <&clock CLK_SMMU_MFCR>, <&clock CLK_MFC>;
+               #iommu-cells = <0>;
+       };
+
+       sysmmu_mfc_l: sysmmu at 11210000 {
+               compatible = "samsung,exynos-sysmmu";
+               reg = <0x11210000 0x1000>;
+               interrupt-parent = <&combiner>;
+               interrupts = <8 5>;
+               power-domains = <&pd_mfc>;
+               clock-names = "sysmmu", "master";
+               clocks = <&clock CLK_SMMU_MFCL>, <&clock CLK_MFC>;
+               #iommu-cells = <0>;
+       };
+
+       sysmmu_tv: sysmmu at 14650000 {
+               compatible = "samsung,exynos-sysmmu";
+               reg = <0x14650000 0x1000>;
+               interrupt-parent = <&combiner>;
+               interrupts = <7 4>;
+               power-domains = <&pd_disp1>;
+               clock-names = "sysmmu", "master";
+               clocks = <&clock CLK_SMMU_TV>, <&clock CLK_MIXER>;
+               #iommu-cells = <0>;
+       };
+
+       sysmmu_fimd1: sysmmu at 14640000 {
+               compatible = "samsung,exynos-sysmmu";
+               reg = <0x14640000 0x1000>;
+               interrupt-parent = <&combiner>;
+               interrupts = <3 2>;
+               power-domains = <&pd_disp1>;
+               clock-names = "sysmmu", "master";
+               clocks = <&clock CLK_SMMU_FIMD1>, <&clock CLK_FIMD1>;
+               #iommu-cells = <0>;
+       };
+
+       sysmmu_g2d: sysmmu at 10A60000 {
+               compatible = "samsung,exynos-sysmmu";
+               reg = <0x10A60000 0x1000>;
+               interrupt-parent = <&combiner>;
+               interrupts = <24 5>;
+               clock-names = "sysmmu", "master";
+               clocks = <&clock CLK_SMMU_2D>, <&clock CLK_G2D>;
+               #iommu-cells = <0>;
+       };
+
+       sysmmu_rotator: sysmmu at 11D40000 {
+               compatible = "samsung,exynos-sysmmu";
+               reg = <0x11D40000 0x1000>;
+               interrupt-parent = <&combiner>;
+               interrupts = <4 0>;
+               clock-names = "sysmmu", "master";
+               clocks = <&clock CLK_SMMU_ROTATOR>, <&clock CLK_ROTATOR>;
+               #iommu-cells = <0>;
+       };
+
+       sysmmu_jpeg: sysmmu at 11F20000 {
+               compatible = "samsung,exynos-sysmmu";
+               reg = <0x11F20000 0x1000>;
+               interrupt-parent = <&combiner>;
+               interrupts = <4 2>;
+               power-domains = <&pd_gsc>;
+               clock-names = "sysmmu", "master";
+               clocks = <&clock CLK_SMMU_JPEG>, <&clock CLK_JPEG>;
+               #iommu-cells = <0>;
+       };
+
+       sysmmu_fimc_isp: sysmmu at 13260000 {
+               compatible = "samsung,exynos-sysmmu";
+               reg = <0x13260000 0x1000>;
+               interrupt-parent = <&combiner>;
+               interrupts = <10 6>;
+               clock-names = "sysmmu";
+               clocks = <&clock CLK_SMMU_FIMC_ISP>;
+               #iommu-cells = <0>;
+       };
+
+       sysmmu_fimc_drc: sysmmu at 13270000 {
+               compatible = "samsung,exynos-sysmmu";
+               reg = <0x13270000 0x1000>;
+               interrupt-parent = <&combiner>;
+               interrupts = <11 6>;
+               clock-names = "sysmmu";
+               clocks = <&clock CLK_SMMU_FIMC_DRC>;
+               #iommu-cells = <0>;
+       };
+
+       sysmmu_fimc_fd: sysmmu at 132A0000 {
+               compatible = "samsung,exynos-sysmmu";
+               reg = <0x132A0000 0x1000>;
+               interrupt-parent = <&combiner>;
+               interrupts = <5 0>;
+               clock-names = "sysmmu";
+               clocks = <&clock CLK_SMMU_FIMC_FD>;
+               #iommu-cells = <0>;
+       };
+
+       sysmmu_fimc_scc: sysmmu at 13280000 {
+               compatible = "samsung,exynos-sysmmu";
+               reg = <0x13280000 0x1000>;
+               interrupt-parent = <&combiner>;
+               interrupts = <5 2>;
+               clock-names = "sysmmu";
+               clocks = <&clock CLK_SMMU_FIMC_SCC>;
+               #iommu-cells = <0>;
+       };
+
+       sysmmu_fimc_scp: sysmmu at 13290000 {
+               compatible = "samsung,exynos-sysmmu";
+               reg = <0x13290000 0x1000>;
+               interrupt-parent = <&combiner>;
+               interrupts = <3 6>;
+               clock-names = "sysmmu";
+               clocks = <&clock CLK_SMMU_FIMC_SCP>;
+               #iommu-cells = <0>;
+       };
+
+       sysmmu_fimc_mcuctl: sysmmu at 132B0000 {
+               compatible = "samsung,exynos-sysmmu";
+               reg = <0x132B0000 0x1000>;
+               interrupt-parent = <&combiner>;
+               interrupts = <5 4>;
+               clock-names = "sysmmu";
+               clocks = <&clock CLK_SMMU_FIMC_MCU>;
+               #iommu-cells = <0>;
+       };
+
+       sysmmu_fimc_odc: sysmmu at 132C0000 {
+               compatible = "samsung,exynos-sysmmu";
+               reg = <0x132C0000 0x1000>;
+               interrupt-parent = <&combiner>;
+               interrupts = <11 0>;
+               clock-names = "sysmmu";
+               clocks = <&clock CLK_SMMU_FIMC_ODC>;
+               #iommu-cells = <0>;
+       };
+
+       sysmmu_fimc_dis0: sysmmu at 132D0000 {
+               compatible = "samsung,exynos-sysmmu";
+               reg = <0x132D0000 0x1000>;
+               interrupt-parent = <&combiner>;
+               interrupts = <10 4>;
+               clock-names = "sysmmu";
+               clocks = <&clock CLK_SMMU_FIMC_DIS0>;
+               #iommu-cells = <0>;
+       };
+
+       sysmmu_fimc_dis1: sysmmu at 132E0000{
+               compatible = "samsung,exynos-sysmmu";
+               reg = <0x132E0000 0x1000>;
+               interrupt-parent = <&combiner>;
+               interrupts = <9 4>;
+               clock-names = "sysmmu";
+               clocks = <&clock CLK_SMMU_FIMC_DIS1>;
+               #iommu-cells = <0>;
+       };
+
+       sysmmu_fimc_3dnr: sysmmu at 132F0000 {
+               compatible = "samsung,exynos-sysmmu";
+               reg = <0x132F0000 0x1000>;
+               interrupt-parent = <&combiner>;
+               interrupts = <5 6>;
+               clock-names = "sysmmu";
+               clocks = <&clock CLK_SMMU_FIMC_3DNR>;
+               #iommu-cells = <0>;
+       };
+
+       sysmmu_fimc_lite0: sysmmu at 13C40000 {
+               compatible = "samsung,exynos-sysmmu";
+               reg = <0x13C40000 0x1000>;
+               interrupt-parent = <&combiner>;
+               interrupts = <3 4>;
+               power-domains = <&pd_gsc>;
+               clock-names = "sysmmu", "master";
+               clocks = <&clock CLK_SMMU_FIMC_LITE0>, <&clock CLK_CAMIF_TOP>;
+               #iommu-cells = <0>;
+       };
+
+       sysmmu_fimc_lite1: sysmmu at 13C50000 {
+               compatible = "samsung,exynos-sysmmu";
+               reg = <0x13C50000 0x1000>;
+               interrupt-parent = <&combiner>;
+               interrupts = <24 1>;
+               power-domains = <&pd_gsc>;
+               clock-names = "sysmmu", "master";
+               clocks = <&clock CLK_SMMU_FIMC_LITE1>, <&clock CLK_CAMIF_TOP>;
+               #iommu-cells = <0>;
+       };
 };
--

1.9.2

_______________________________________________
iommu mailing list
iommu at lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

#6 lore raw

PATCH v5 4/18 ARM: dts: exynos5250: add sysmmu nodes

In reply to Marek Szyprowski

Am 23.01.2015 um 16:51 schrieb Marek Szyprowski:

Quoted 134 lines
---
 arch/arm/boot/dts/exynos5250.dtsi | 250 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 250 insertions(+)
arch/arm/boot/dts/exynos5250.dtsi +65 -0
index ae22bd9..8583b9e 100644
@@ -224,6 +224,7 @@
 		interrupts = <0 91 0>;
 		clocks = <&clock CLK_G2D>;
 		clock-names = "fimg2d";
+		iommus = <&sysmmu_g2d>;
 	};
 
 	mfc: codec at 11000000 {
@@ -233,6 +234,8 @@
 		power-domains = <&pd_mfc>;
 		clocks = <&clock CLK_MFC>;
 		clock-names = "mfc";
+		iommus = <&sysmmu_mfc_l>, <&sysmmu_mfc_r>;
+		iommu-names = "left", "right";
 	};
 
 	rtc: rtc at 101E0000 {
@@ -693,6 +696,7 @@
 		power-domains = <&pd_gsc>;
 		clocks = <&clock CLK_GSCL0>;
 		clock-names = "gscl";
+		iommu = <&sysmmu_gsc1>;
 	};
 
 	gsc_1:  gsc at 13e10000 {
@@ -702,6 +706,7 @@
 		power-domains = <&pd_gsc>;
 		clocks = <&clock CLK_GSCL1>;
 		clock-names = "gscl";
+		iommu = <&sysmmu_gsc1>;
 	};
 
 	gsc_2:  gsc at 13e20000 {
@@ -711,6 +716,7 @@
 		power-domains = <&pd_gsc>;
 		clocks = <&clock CLK_GSCL2>;
 		clock-names = "gscl";
+		iommu = <&sysmmu_gsc2>;
 	};
 
 	gsc_3:  gsc at 13e30000 {
@@ -720,6 +726,7 @@
 		power-domains = <&pd_gsc>;
 		clocks = <&clock CLK_GSCL3>;
 		clock-names = "gscl";
+		iommu = <&sysmmu_gsc3>;
 	};
 
 	hdmi: hdmi {
@@ -743,6 +750,7 @@
 		clocks = <&clock CLK_MIXER>, <&clock CLK_HDMI>,
 			 <&clock CLK_SCLK_HDMI>;
 		clock-names = "mixer", "hdmi", "sclk_hdmi";
+		iommus = <&sysmmu_tv>;
 	};
 
 	dp_phy: video-phy at 10040720 {
@@ -763,6 +771,7 @@
 		power-domains = <&pd_disp1>;
 		clocks = <&clock CLK_SCLK_FIMD1>, <&clock CLK_FIMD1>;
 		clock-names = "sclk_fimd", "fimd";
+		iommus = <&sysmmu_fimd1>;
 	};
 
 	adc: adc at 12D10000 {
@@ -784,4 +793,245 @@
 		clocks = <&clock CLK_SSS>;
 		clock-names = "secss";
 	};
+
+	sysmmu_gsc0: sysmmu at 13E80000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x13E80000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <2 0>;
+		power-domains = <&pd_gsc>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_GSCL0>, <&clock CLK_GSCL0>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_gsc1: sysmmu at 13E90000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x13E90000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <2 2>;
+		power-domains = <&pd_gsc>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_GSCL1>, <&clock CLK_GSCL1>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_gsc2: sysmmu at 13EA0000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x13EA0000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <2 4>;
+		power-domains = <&pd_gsc>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_GSCL2>, <&clock CLK_GSCL2>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_gsc3: sysmmu at 13EB0000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x13EB0000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <2 6>;
+		power-domains = <&pd_gsc>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_GSCL3>, <&clock CLK_GSCL3>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_mfc_r: sysmmu at 11200000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x11200000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <6 2>;
+		power-domains = <&pd_mfc>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_MFCR>, <&clock CLK_MFC>;
+		#iommu-cells = <0>;
+	};
+

arch/arm/boot/dts/exynos5250.dtsi line 861

Quoted 10 lines
arch/arm/boot/dts/exynos5250.dtsi +10 -0
+	sysmmu_mfc_l: sysmmu at 11210000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x11210000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <8 5>;
+		power-domains = <&pd_mfc>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_MFCL>, <&clock CLK_MFC>;
+		#iommu-cells = <0>;
+	};

These two nodes (and further ones below) seem sorted wrongly. Please order by unit address.

Regards,
Andreas

Quoted 176 lines
arch/arm/boot/dts/exynos5250.dtsi +175 -0
+
+	sysmmu_tv: sysmmu at 14650000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x14650000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <7 4>;
+		power-domains = <&pd_disp1>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_TV>, <&clock CLK_MIXER>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_fimd1: sysmmu at 14640000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x14640000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <3 2>;
+		power-domains = <&pd_disp1>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_FIMD1>, <&clock CLK_FIMD1>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_g2d: sysmmu at 10A60000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x10A60000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <24 5>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_2D>, <&clock CLK_G2D>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_rotator: sysmmu at 11D40000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x11D40000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <4 0>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_ROTATOR>, <&clock CLK_ROTATOR>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_jpeg: sysmmu at 11F20000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x11F20000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <4 2>;
+		power-domains = <&pd_gsc>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_JPEG>, <&clock CLK_JPEG>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_fimc_isp: sysmmu at 13260000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x13260000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <10 6>;
+		clock-names = "sysmmu";
+		clocks = <&clock CLK_SMMU_FIMC_ISP>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_fimc_drc: sysmmu at 13270000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x13270000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <11 6>;
+		clock-names = "sysmmu";
+		clocks = <&clock CLK_SMMU_FIMC_DRC>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_fimc_fd: sysmmu at 132A0000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x132A0000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <5 0>;
+		clock-names = "sysmmu";
+		clocks = <&clock CLK_SMMU_FIMC_FD>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_fimc_scc: sysmmu at 13280000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x13280000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <5 2>;
+		clock-names = "sysmmu";
+		clocks = <&clock CLK_SMMU_FIMC_SCC>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_fimc_scp: sysmmu at 13290000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x13290000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <3 6>;
+		clock-names = "sysmmu";
+		clocks = <&clock CLK_SMMU_FIMC_SCP>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_fimc_mcuctl: sysmmu at 132B0000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x132B0000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <5 4>;
+		clock-names = "sysmmu";
+		clocks = <&clock CLK_SMMU_FIMC_MCU>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_fimc_odc: sysmmu at 132C0000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x132C0000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <11 0>;
+		clock-names = "sysmmu";
+		clocks = <&clock CLK_SMMU_FIMC_ODC>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_fimc_dis0: sysmmu at 132D0000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x132D0000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <10 4>;
+		clock-names = "sysmmu";
+		clocks = <&clock CLK_SMMU_FIMC_DIS0>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_fimc_dis1: sysmmu at 132E0000{
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x132E0000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <9 4>;
+		clock-names = "sysmmu";
+		clocks = <&clock CLK_SMMU_FIMC_DIS1>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_fimc_3dnr: sysmmu at 132F0000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x132F0000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <5 6>;
+		clock-names = "sysmmu";
+		clocks = <&clock CLK_SMMU_FIMC_3DNR>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_fimc_lite0: sysmmu at 13C40000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x13C40000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <3 4>;
+		power-domains = <&pd_gsc>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_FIMC_LITE0>, <&clock CLK_CAMIF_TOP>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_fimc_lite1: sysmmu at 13C50000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x13C50000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <24 1>;
+		power-domains = <&pd_gsc>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_FIMC_LITE1>, <&clock CLK_CAMIF_TOP>;
+		#iommu-cells = <0>;
+	};
 };
Signature · 3 lines
SUSE Linux GmbH, Maxfeldstr. 5, 90409 N?rnberg, Germany
GF: Felix Imend?rffer, Jane Smithard, Jennifer Guild, Dilip Upmanyu,
Graham Norton; HRB 21284 (AG N?rnberg)
author maintainer
#7 lore raw

PATCH v5 5/18 ARM: dts: exynos5420: add sysmmu nodes

In reply to Marek Szyprowski
---
 arch/arm/boot/dts/exynos5420.dtsi | 181 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 181 insertions(+)
arch/arm/boot/dts/exynos5420.dtsi +181 -0
index 1b62410..b8f1c9f 100644
@@ -179,6 +179,8 @@
 		clocks = <&clock CLK_MFC>;
 		clock-names = "mfc";
 		power-domains = <&mfc_pd>;
+		iommus = <&sysmmu_mfc_l>, <&sysmmu_mfc_r>;
+		iommu-names = "left", "right";
 	};
 
 	mmc_0: mmc at 12200000 {
@@ -556,6 +558,8 @@
 		clocks = <&clock CLK_SCLK_FIMD1>, <&clock CLK_FIMD1>;
 		clock-names = "sclk_fimd", "fimd";
 		power-domains = <&disp_pd>;
+		iommus = <&sysmmu_fimd1_0>, <&sysmmu_fimd1_1>;
+		iommu-names = "m0", "m1";
 	};
 
 	adc: adc at 12D10000 {
@@ -743,6 +747,7 @@
 		clocks = <&clock CLK_MIXER>, <&clock CLK_HDMI>,
 			 <&clock CLK_SCLK_HDMI>;
 		clock-names = "mixer", "hdmi", "sclk_hdmi";
+		iommus = <&sysmmu_tv>;
 		power-domains = <&disp_pd>;
 	};
 
@@ -753,6 +758,7 @@
 		clocks = <&clock CLK_GSCL0>;
 		clock-names = "gscl";
 		power-domains = <&gsc_pd>;
+		iommus = <&sysmmu_gscl0>;
 	};
 
 	gsc_1: video-scaler at 13e10000 {
@@ -762,6 +768,7 @@
 		clocks = <&clock CLK_GSCL1>;
 		clock-names = "gscl";
 		power-domains = <&gsc_pd>;
+		iommus = <&sysmmu_gscl1>;
 	};
 
 	pmu_system_controller: system-controller at 10040000 {
@@ -925,4 +932,178 @@
 		samsung,sysreg-phandle = <&sysreg_system_controller>;
 		samsung,pmureg-phandle = <&pmu_system_controller>;
 	};
+
+	sysmmu_g2dr: sysmmu at 0x10A60000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x10A60000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <24 5>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_G2D>, <&clock CLK_G2D>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_g2dw: sysmmu at 0x10A70000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x10A70000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <22 2>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_G2D>, <&clock CLK_G2D>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_tv: sysmmu at 0x14650000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x14650000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <7 4>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_MIXER>, <&clock CLK_MIXER>;
+		samsung,power-domain = <&disp_pd>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_gscl0: sysmmu at 0x13E80000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x13E80000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <2 0>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_GSCL0>, <&clock CLK_GSCL0>;
+		power-domains = <&gsc_pd>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_gscl1: sysmmu at 0x13E90000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x13E90000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <2 2>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_GSCL1>, <&clock CLK_GSCL1>;
+		power-domains = <&gsc_pd>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_scaler0r: sysmmu at 0x12880000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x12880000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <22 4>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_MSCL0>, <&clock CLK_MSCL0>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_scaler1r: sysmmu at 0x12890000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x12890000 0x1000>;
+		interrupts = <0 186 0>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_MSCL1>, <&clock CLK_MSCL1>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_scaler2r: sysmmu at 0x128A0000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x128A0000 0x1000>;
+		interrupts = <0 188 0>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_MSCL2>, <&clock CLK_MSCL2>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_scaler0w: sysmmu at 0x128C0000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x128C0000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <27 2>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_MSCL0>, <&clock CLK_MSCL0>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_scaler1w: sysmmu at 0x128D0000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x128D0000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <22 6>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_MSCL1>, <&clock CLK_MSCL1>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_scaler2w: sysmmu at 0x128E0000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x128E0000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <19 6>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_MSCL2>, <&clock CLK_MSCL2>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_jpeg: sysmmu at 0x11F10000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x11F10000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <4 2>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_JPEG>, <&clock CLK_JPEG>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_jpeg2: sysmmu at 0x11F20000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x11F20000 0x1000>;
+		interrupts = <0 169 0>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_JPEG2>, <&clock CLK_JPEG2>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_mfc_l: sysmmu at 0x11200000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x11200000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <6 2>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_MFCL>, <&clock CLK_MFC>;
+		power-domains = <&mfc_pd>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_mfc_r: sysmmu at 0x11210000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x11210000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <8 5>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_MFCR>, <&clock CLK_MFC>;
+		power-domains = <&mfc_pd>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_fimd1_0: sysmmu at 0x14640000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x14640000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <3 2>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_FIMD1M0>, <&clock CLK_FIMD1>;
+		samsung,power-domain = <&disp_pd>;
+		#iommu-cells = <0>;
+	};
+
+	sysmmu_fimd1_1: sysmmu at 0x14680000 {
+		compatible = "samsung,exynos-sysmmu";
+		reg = <0x14680000 0x1000>;
+		interrupt-parent = <&combiner>;
+		interrupts = <3 0>;
+		clock-names = "sysmmu", "master";
+		clocks = <&clock CLK_SMMU_FIMD1M0>, <&clock CLK_FIMD1>;
+		samsung,power-domain = <&disp_pd>;
+		#iommu-cells = <0>;
+	};
 };
Signature · 1 line
1.9.2
#8 lore raw

PATCH v5 5/18 ARM: dts: exynos5420: add sysmmu nodes

Am 23.01.2015 um 16:51 schrieb Marek Szyprowski:

Quoted 9 lines
---
 arch/arm/boot/dts/exynos5420.dtsi | 181 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 181 insertions(+)
arch/arm/boot/dts/exynos5420.dtsi +0 -0
index 1b62410..b8f1c9f 100644

[...]

arch/arm/boot/dts/exynos5420.dtsi line 936

Quoted 6 lines
arch/arm/boot/dts/exynos5420.dtsi +2 -0
@@ -925,4 +932,178 @@
 		samsung,sysreg-phandle = <&sysreg_system_controller>;
 		samsung,pmureg-phandle = <&pmu_system_controller>;
 	};
+
+	sysmmu_g2dr: sysmmu at 0x10A60000 {

[snip]

Unit addresses are without 0x. Please also check the sort order.

Regards,
Andreas

Signature · 3 lines
SUSE Linux GmbH, Maxfeldstr. 5, 90409 N?rnberg, Germany
GF: Felix Imend?rffer, Jane Smithard, Jennifer Guild, Dilip Upmanyu,
Graham Norton; HRB 21284 (AG N?rnberg)
author maintainer
#9 lore raw

PATCH v5 6/18 iommu: exynos: don't read version register on every tlb operation

In reply to Marek Szyprowski

This patch removes reading of REG_MMU_VERSION register on every tlb operation and caches SYSMMU version in driver's internal data.

---
 drivers/iommu/exynos-iommu.c | 13 +++++--------
 1 file changed, 5 insertions(+), 8 deletions(-)
drivers/iommu/exynos-iommu.c +5 -8
index 7ce5273..b6c8612 100644
@@ -212,6 +212,7 @@ struct sysmmu_drvdata {
 	spinlock_t lock;
 	struct iommu_domain *domain;
 	phys_addr_t pgtable;
+	int version;
 };
 
 static bool set_sysmmu_active(struct sysmmu_drvdata *data)
@@ -238,11 +239,6 @@ static void sysmmu_unblock(void __iomem *sfrbase)
 	__raw_writel(CTRL_ENABLE, sfrbase + REG_MMU_CTRL);
 }
 
-static unsigned int __raw_sysmmu_version(struct sysmmu_drvdata *data)
-{
-	return MMU_RAW_VER(__raw_readl(data->sfrbase + REG_MMU_VERSION));
-}
-
 static bool sysmmu_block(void __iomem *sfrbase)
 {
 	int i = 120;
@@ -402,7 +398,7 @@ static void __sysmmu_init_config(struct sysmmu_drvdata *data)
 	unsigned int cfg = CFG_LRU | CFG_QOS(15);
 	unsigned int ver;
 
-	ver = __raw_sysmmu_version(data);
+	ver = MMU_RAW_VER(__raw_readl(data->sfrbase + REG_MMU_VERSION));
 	if (MMU_MAJ_VER(ver) == 3) {
 		if (MMU_MIN_VER(ver) >= 2) {
 			cfg |= CFG_FLPDCACHE;
@@ -416,6 +412,7 @@ static void __sysmmu_init_config(struct sysmmu_drvdata *data)
 	}
 
 	__raw_writel(cfg, data->sfrbase + REG_MMU_CFG);
+	data->version = ver;
 }
 
 static void __sysmmu_enable_nocount(struct sysmmu_drvdata *data)
@@ -525,7 +522,7 @@ static bool exynos_sysmmu_disable(struct device *dev)
 static void __sysmmu_tlb_invalidate_flpdcache(struct sysmmu_drvdata *data,
 					      sysmmu_iova_t iova)
 {
-	if (__raw_sysmmu_version(data) == MAKE_MMU_VER(3, 3))
+	if (data->version == MAKE_MMU_VER(3, 3))
 		__raw_writel(iova | 0x1, data->sfrbase + REG_MMU_FLUSH_ENTRY);
 }
 
@@ -574,7 +571,7 @@ static void sysmmu_tlb_invalidate_entry(struct device *dev, sysmmu_iova_t iova,
 		 * 1MB page can be cached in one of all sets.
 		 * 64KB page can be one of 16 consecutive sets.
 		 */
-		if (MMU_MAJ_VER(__raw_sysmmu_version(data)) == 2)
+		if (MMU_MAJ_VER(data->version) == 2)
 			num_inv = min_t(unsigned int, size / PAGE_SIZE, 64);
 
 		if (sysmmu_block(data->sfrbase)) {
Signature · 1 line
1.9.2
author maintainer
#10 lore raw

PATCH v5 7/18 iommu: exynos: remove unused functions

In reply to Marek Szyprowski

This patch removes two unneeded functions, which are not a part of generic IOMMU API and were never used by any other driver.

---
 drivers/iommu/exynos-iommu.c | 31 -------------------------------
 1 file changed, 31 deletions(-)
drivers/iommu/exynos-iommu.c +0 -31
index b6c8612..3c82411 100644
@@ -490,13 +490,6 @@ static int __exynos_sysmmu_enable(struct device *dev, phys_addr_t pgtable,
 	return ret;
 }
 
-int exynos_sysmmu_enable(struct device *dev, phys_addr_t pgtable)
-{
-	BUG_ON(!memblock_is_memory(pgtable));
-
-	return __exynos_sysmmu_enable(dev, pgtable, NULL);
-}
-
 static bool exynos_sysmmu_disable(struct device *dev)
 {
 	unsigned long flags;
@@ -588,30 +581,6 @@ static void sysmmu_tlb_invalidate_entry(struct device *dev, sysmmu_iova_t iova,
 	spin_unlock_irqrestore(&data->lock, flags);
 }
 
-void exynos_sysmmu_tlb_invalidate(struct device *dev)
-{
-	struct exynos_iommu_owner *owner = dev->archdata.iommu;
-	unsigned long flags;
-	struct sysmmu_drvdata *data;
-
-	data = dev_get_drvdata(owner->sysmmu);
-
-	spin_lock_irqsave(&data->lock, flags);
-	if (is_sysmmu_active(data)) {
-		if (!IS_ERR(data->clk_master))
-			clk_enable(data->clk_master);
-		if (sysmmu_block(data->sfrbase)) {
-			__sysmmu_tlb_invalidate(data->sfrbase);
-			sysmmu_unblock(data->sfrbase);
-		}
-		if (!IS_ERR(data->clk_master))
-			clk_disable(data->clk_master);
-	} else {
-		dev_dbg(dev, "disabled. Skipping TLB invalidation\n");
-	}
-	spin_unlock_irqrestore(&data->lock, flags);
-}
-
 static int __init exynos_sysmmu_probe(struct platform_device *pdev)
 {
 	int irq, ret;
Signature · 1 line
1.9.2
author maintainer
#11 lore raw

PATCH v5 8/18 iommu: exynos: remove useless spinlock

In reply to Marek Szyprowski

This patch removes useless spinlocks and other unused members from struct exynos_iommu_owner. There is no point is protecting this structure by spinlock because content of this structure doesn't change and other structures have their own spinlocks.

---
 drivers/iommu/exynos-iommu.c | 11 -----------
 1 file changed, 11 deletions(-)
drivers/iommu/exynos-iommu.c +0 -11
index 3c82411..aa8c4b0 100644
@@ -189,9 +189,6 @@ struct exynos_iommu_owner {
 	struct list_head client; /* entry of exynos_iommu_domain.clients */
 	struct device *dev;
 	struct device *sysmmu;
-	struct iommu_domain *domain;
-	void *vmm_data;         /* IO virtual memory manager's data */
-	spinlock_t lock;        /* Lock to preserve consistency of System MMU */
 };
 
 struct exynos_iommu_domain {
@@ -477,16 +474,12 @@ static int __exynos_sysmmu_enable(struct device *dev, phys_addr_t pgtable,
 
 	BUG_ON(!has_sysmmu(dev));
 
-	spin_lock_irqsave(&owner->lock, flags);
-
 	data = dev_get_drvdata(owner->sysmmu);
 
 	ret = __sysmmu_enable(data, pgtable, domain);
 	if (ret >= 0)
 		data->master = dev;
 
-	spin_unlock_irqrestore(&owner->lock, flags);
-
 	return ret;
 }
 
@@ -499,16 +492,12 @@ static bool exynos_sysmmu_disable(struct device *dev)
 
 	BUG_ON(!has_sysmmu(dev));
 
-	spin_lock_irqsave(&owner->lock, flags);
-
 	data = dev_get_drvdata(owner->sysmmu);
 
 	disabled = __sysmmu_disable(data);
 	if (disabled)
 		data->master = NULL;
 
-	spin_unlock_irqrestore(&owner->lock, flags);
-
 	return disabled;
 }
 
Signature · 1 line
1.9.2
author maintainer
#12 lore raw

PATCH v5 9/18 iommu: exynos: refactor function parameters to simplify code

In reply to Marek Szyprowski

This patch simplifies the code by:
- refactoring function parameters from struct device pointer to direct pointer to struct sysmmu drvdata
- moving list_head enteries from struct exynos_iommu_owner directly to struct sysmmu_drvdata

---
 drivers/iommu/exynos-iommu.c | 93 ++++++++++++++++++++++----------------------
 1 file changed, 46 insertions(+), 47 deletions(-)
drivers/iommu/exynos-iommu.c +46 -47
index aa8c4b0..862261f 100644
@@ -186,8 +186,6 @@ static char *sysmmu_fault_name[SYSMMU_FAULTS_NUM] = {
 
 /* attached to dev.archdata.iommu of the master device */
 struct exynos_iommu_owner {
-	struct list_head client; /* entry of exynos_iommu_domain.clients */
-	struct device *dev;
 	struct device *sysmmu;
 };
 
@@ -208,6 +206,7 @@ struct sysmmu_drvdata {
 	int activations;
 	spinlock_t lock;
 	struct iommu_domain *domain;
+	struct list_head domain_node;
 	phys_addr_t pgtable;
 	int version;
 };
@@ -508,12 +507,10 @@ static void __sysmmu_tlb_invalidate_flpdcache(struct sysmmu_drvdata *data,
 		__raw_writel(iova | 0x1, data->sfrbase + REG_MMU_FLUSH_ENTRY);
 }
 
-static void sysmmu_tlb_invalidate_flpdcache(struct device *dev,
+static void sysmmu_tlb_invalidate_flpdcache(struct sysmmu_drvdata *data,
 					    sysmmu_iova_t iova)
 {
 	unsigned long flags;
-	struct exynos_iommu_owner *owner = dev->archdata.iommu;
-	struct sysmmu_drvdata *data = dev_get_drvdata(owner->sysmmu);
 
 	if (!IS_ERR(data->clk_master))
 		clk_enable(data->clk_master);
@@ -527,14 +524,10 @@ static void sysmmu_tlb_invalidate_flpdcache(struct device *dev,
 		clk_disable(data->clk_master);
 }
 
-static void sysmmu_tlb_invalidate_entry(struct device *dev, sysmmu_iova_t iova,
-					size_t size)
+static void sysmmu_tlb_invalidate_entry(struct sysmmu_drvdata *data,
+					sysmmu_iova_t iova, size_t size)
 {
-	struct exynos_iommu_owner *owner = dev->archdata.iommu;
 	unsigned long flags;
-	struct sysmmu_drvdata *data;
-
-	data = dev_get_drvdata(owner->sysmmu);
 
 	spin_lock_irqsave(&data->lock, flags);
 	if (is_sysmmu_active(data)) {
@@ -564,8 +557,8 @@ static void sysmmu_tlb_invalidate_entry(struct device *dev, sysmmu_iova_t iova,
 		if (!IS_ERR(data->clk_master))
 			clk_disable(data->clk_master);
 	} else {
-		dev_dbg(dev, "disabled. Skipping TLB invalidation @ %#x\n",
-			iova);
+		dev_dbg(data->master,
+			"disabled. Skipping TLB invalidation @ %#x\n", iova);
 	}
 	spin_unlock_irqrestore(&data->lock, flags);
 }
@@ -703,7 +696,7 @@ err_pgtable:
 static void exynos_iommu_domain_destroy(struct iommu_domain *domain)
 {
 	struct exynos_iommu_domain *priv = domain->priv;
-	struct exynos_iommu_owner *owner;
+	struct sysmmu_drvdata *data;
 	unsigned long flags;
 	int i;
 
@@ -711,14 +704,12 @@ static void exynos_iommu_domain_destroy(struct iommu_domain *domain)
 
 	spin_lock_irqsave(&priv->lock, flags);
 
-	list_for_each_entry(owner, &priv->clients, client) {
-		while (!exynos_sysmmu_disable(owner->dev))
-			; /* until System MMU is actually disabled */
+	list_for_each_entry(data, &priv->clients, domain_node) {
+		if (__sysmmu_disable(data))
+			data->master = NULL;
+		list_del_init(&data->domain_node);
 	}
 
-	while (!list_empty(&priv->clients))
-		list_del_init(priv->clients.next);
-
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	for (i = 0; i < NUM_LV1ENTRIES; i++)
@@ -737,20 +728,26 @@ static int exynos_iommu_attach_device(struct iommu_domain *domain,
 {
 	struct exynos_iommu_owner *owner = dev->archdata.iommu;
 	struct exynos_iommu_domain *priv = domain->priv;
+	struct sysmmu_drvdata *data;
 	phys_addr_t pagetable = virt_to_phys(priv->pgtable);
 	unsigned long flags;
-	int ret;
+	int ret = -ENODEV;
 
-	spin_lock_irqsave(&priv->lock, flags);
+	if (!has_sysmmu(dev))
+		return -ENODEV;
 
-	ret = __exynos_sysmmu_enable(dev, pagetable, domain);
-	if (ret == 0) {
-		list_add_tail(&owner->client, &priv->clients);
-		owner->domain = domain;
+	data = dev_get_drvdata(owner->sysmmu);
+	if (data) {
+		ret = __sysmmu_enable(data, pagetable, domain);
+		if (ret >= 0) {
+			data->master = dev;
+
+			spin_lock_irqsave(&priv->lock, flags);
+			list_add_tail(&data->domain_node, &priv->clients);
+			spin_unlock_irqrestore(&priv->lock, flags);
+		}
 	}
 
-	spin_unlock_irqrestore(&priv->lock, flags);
-
 	if (ret < 0) {
 		dev_err(dev, "%s: Failed to attach IOMMU with pgtable %pa\n",
 					__func__, &pagetable);
@@ -766,26 +763,29 @@ static int exynos_iommu_attach_device(struct iommu_domain *domain,
 static void exynos_iommu_detach_device(struct iommu_domain *domain,
 				    struct device *dev)
 {
-	struct exynos_iommu_owner *owner;
 	struct exynos_iommu_domain *priv = domain->priv;
 	phys_addr_t pagetable = virt_to_phys(priv->pgtable);
+	struct sysmmu_drvdata *data;
 	unsigned long flags;
+	int found = 0;
 
-	spin_lock_irqsave(&priv->lock, flags);
+	if (!has_sysmmu(dev))
+		return;
 
-	list_for_each_entry(owner, &priv->clients, client) {
-		if (owner == dev->archdata.iommu) {
-			if (exynos_sysmmu_disable(dev)) {
-				list_del_init(&owner->client);
-				owner->domain = NULL;
+	spin_lock_irqsave(&priv->lock, flags);
+	list_for_each_entry(data, &priv->clients, domain_node) {
+		if (data->master == dev) {
+			if (__sysmmu_disable(data)) {
+				data->master = NULL;
+				list_del_init(&data->domain_node);
 			}
+			found = true;
 			break;
 		}
 	}
-
 	spin_unlock_irqrestore(&priv->lock, flags);
 
-	if (owner == dev->archdata.iommu)
+	if (found)
 		dev_dbg(dev, "%s: Detached IOMMU with pgtable %pa\n",
 					__func__, &pagetable);
 	else
@@ -832,12 +832,11 @@ static sysmmu_pte_t *alloc_lv2entry(struct exynos_iommu_domain *priv,
 		 * not currently mapped.
 		 */
 		if (need_flush_flpd_cache) {
-			struct exynos_iommu_owner *owner;
+			struct sysmmu_drvdata *data;
 
 			spin_lock(&priv->lock);
-			list_for_each_entry(owner, &priv->clients, client)
-				sysmmu_tlb_invalidate_flpdcache(
-							owner->dev, iova);
+			list_for_each_entry(data, &priv->clients, domain_node)
+				sysmmu_tlb_invalidate_flpdcache(data, iova);
 			spin_unlock(&priv->lock);
 		}
 	}
@@ -872,13 +871,13 @@ static int lv1set_section(struct exynos_iommu_domain *priv,
 
 	spin_lock(&priv->lock);
 	if (lv1ent_page_zero(sent)) {
-		struct exynos_iommu_owner *owner;
+		struct sysmmu_drvdata *data;
 		/*
 		 * Flushing FLPD cache in System MMU v3.3 that may cache a FLPD
 		 * entry by speculative prefetch of SLPD which has no mapping.
 		 */
-		list_for_each_entry(owner, &priv->clients, client)
-			sysmmu_tlb_invalidate_flpdcache(owner->dev, iova);
+		list_for_each_entry(data, &priv->clients, domain_node)
+			sysmmu_tlb_invalidate_flpdcache(data, iova);
 	}
 	spin_unlock(&priv->lock);
 
@@ -983,13 +982,13 @@ static int exynos_iommu_map(struct iommu_domain *domain, unsigned long l_iova,
 static void exynos_iommu_tlb_invalidate_entry(struct exynos_iommu_domain *priv,
 						sysmmu_iova_t iova, size_t size)
 {
-	struct exynos_iommu_owner *owner;
+	struct sysmmu_drvdata *data;
 	unsigned long flags;
 
 	spin_lock_irqsave(&priv->lock, flags);
 
-	list_for_each_entry(owner, &priv->clients, client)
-		sysmmu_tlb_invalidate_entry(owner->dev, iova, size);
+	list_for_each_entry(data, &priv->clients, domain_node)
+		sysmmu_tlb_invalidate_entry(data, iova, size);
 
 	spin_unlock_irqrestore(&priv->lock, flags);
 }
Signature · 1 line
1.9.2
author maintainer
#13 lore raw

PATCH v5 10/18 iommu: exynos: remove unused functions, part 2

In reply to Marek Szyprowski

After refactoring functions to use pointer to struct sysmmu_drvdata directly, some functions became useless and thus never used, so remove them completely.

---
 drivers/iommu/exynos-iommu.c | 43 -------------------------------------------
 1 file changed, 43 deletions(-)
drivers/iommu/exynos-iommu.c +0 -43
index 862261f..e62cb96 100644
@@ -457,49 +457,6 @@ static int __sysmmu_enable(struct sysmmu_drvdata *data,
 	return ret;
 }
 
-/* __exynos_sysmmu_enable: Enables System MMU
- *
- * returns -error if an error occurred and System MMU is not enabled,
- * 0 if the System MMU has been just enabled and 1 if System MMU was already
- * enabled before.
- */
-static int __exynos_sysmmu_enable(struct device *dev, phys_addr_t pgtable,
-				  struct iommu_domain *domain)
-{
-	int ret = 0;
-	unsigned long flags;
-	struct exynos_iommu_owner *owner = dev->archdata.iommu;
-	struct sysmmu_drvdata *data;
-
-	BUG_ON(!has_sysmmu(dev));
-
-	data = dev_get_drvdata(owner->sysmmu);
-
-	ret = __sysmmu_enable(data, pgtable, domain);
-	if (ret >= 0)
-		data->master = dev;
-
-	return ret;
-}
-
-static bool exynos_sysmmu_disable(struct device *dev)
-{
-	unsigned long flags;
-	bool disabled = true;
-	struct exynos_iommu_owner *owner = dev->archdata.iommu;
-	struct sysmmu_drvdata *data;
-
-	BUG_ON(!has_sysmmu(dev));
-
-	data = dev_get_drvdata(owner->sysmmu);
-
-	disabled = __sysmmu_disable(data);
-	if (disabled)
-		data->master = NULL;
-
-	return disabled;
-}
-
 static void __sysmmu_tlb_invalidate_flpdcache(struct sysmmu_drvdata *data,
 					      sysmmu_iova_t iova)
 {
Signature · 1 line
1.9.2
author maintainer
#14 lore raw

PATCH v5 11/18 iommu: exynos: remove useless device_add/remove callbacks

In reply to Marek Szyprowski

The driver doesn't need to do anything important in device add/remove callbacks, because initialization will be done from device-tree specific callbacks added later. IOMMU groups created by current code were never used.

---
 drivers/iommu/exynos-iommu.c | 28 ----------------------------
 1 file changed, 28 deletions(-)
drivers/iommu/exynos-iommu.c +0 -28
index e62cb96..e40e699 100644
@@ -1055,32 +1055,6 @@ static phys_addr_t exynos_iommu_iova_to_phys(struct iommu_domain *domain,
 	return phys;
 }
 
-static int exynos_iommu_add_device(struct device *dev)
-{
-	struct iommu_group *group;
-	int ret;
-
-	group = iommu_group_get(dev);
-
-	if (!group) {
-		group = iommu_group_alloc();
-		if (IS_ERR(group)) {
-			dev_err(dev, "Failed to allocate IOMMU group\n");
-			return PTR_ERR(group);
-		}
-	}
-
-	ret = iommu_group_add_device(group, dev);
-	iommu_group_put(group);
-
-	return ret;
-}
-
-static void exynos_iommu_remove_device(struct device *dev)
-{
-	iommu_group_remove_device(dev);
-}
-
 static const struct iommu_ops exynos_iommu_ops = {
 	.domain_init = exynos_iommu_domain_init,
 	.domain_destroy = exynos_iommu_domain_destroy,
@@ -1090,8 +1064,6 @@ static const struct iommu_ops exynos_iommu_ops = {
 	.unmap = exynos_iommu_unmap,
 	.map_sg = default_iommu_map_sg,
 	.iova_to_phys = exynos_iommu_iova_to_phys,
-	.add_device = exynos_iommu_add_device,
-	.remove_device = exynos_iommu_remove_device,
 	.pgsize_bitmap = SECT_SIZE | LPAGE_SIZE | SPAGE_SIZE,
 };
 
Signature · 1 line
1.9.2
#15 lore raw

PATCH v5 11/18 iommu: exynos: remove useless device_add/remove callbacks

Hi Marek,

Thank you for the patch.

Quoted 4 lines · On Friday 23 January 2015 16:51:21 Marek Szyprowski wrote:

The driver doesn't need to do anything important in device add/remove callbacks, because initialization will be done from device-tree specific callbacks added later. IOMMU groups created by current code were never used.

IOMMU groups still seem a bit unclear to me. Will Deacon has nicely explained
what they represent in http://lists.infradead.org/pipermail/linux-arm-kernel/2014-December/310816.html. The IOMMU core doesn't make groups mandatory, but requires them in some code paths.

For example the coldplug device add function add_iommu_group() called for all devices already registered when bus_set_iommu() is called will try to warn of devices added multiple times with a WARN_ON(dev->iommu_group). Another example is the iommu_bus_notifier() function which will call the remove_device() operation only when dev->iommu_group isn't NULL.

I'm thus unsure whether groups should be made mandatory, or whether the IOMMU core should be fixed to make them really optional (or, third option, whether there's something I haven't understood properly).

Quoted 50 lines
---
 drivers/iommu/exynos-iommu.c | 28 ----------------------------
 1 file changed, 28 deletions(-)
drivers/iommu/exynos-iommu.c +0 -28
index e62cb96..e40e699 100644
@@ -1055,32 +1055,6 @@ static phys_addr_t exynos_iommu_iova_to_phys(struct
 iommu_domain *domain, return phys;
 }
 
-static int exynos_iommu_add_device(struct device *dev)
-{
-	struct iommu_group *group;
-	int ret;
-
-	group = iommu_group_get(dev);
-
-	if (!group) {
-		group = iommu_group_alloc();
-		if (IS_ERR(group)) {
-			dev_err(dev, "Failed to allocate IOMMU group\n");
-			return PTR_ERR(group);
-		}
-	}
-
-	ret = iommu_group_add_device(group, dev);
-	iommu_group_put(group);
-
-	return ret;
-}
-
-static void exynos_iommu_remove_device(struct device *dev)
-{
-	iommu_group_remove_device(dev);
-}
-
 static const struct iommu_ops exynos_iommu_ops = {
 	.domain_init = exynos_iommu_domain_init,
 	.domain_destroy = exynos_iommu_domain_destroy,
@@ -1090,8 +1064,6 @@ static const struct iommu_ops exynos_iommu_ops = {
 	.unmap = exynos_iommu_unmap,
 	.map_sg = default_iommu_map_sg,
 	.iova_to_phys = exynos_iommu_iova_to_phys,
-	.add_device = exynos_iommu_add_device,
-	.remove_device = exynos_iommu_remove_device,
 	.pgsize_bitmap = SECT_SIZE | LPAGE_SIZE | SPAGE_SIZE,
 };
Signature · 3 lines
Regards,

Laurent Pinchart
maintainer
#16 lore raw

PATCH v5 11/18 iommu: exynos: remove useless device_add/remove callbacks

Hi Laurent,

Quoted 12 lines · Laurent Pinchart

IOMMU groups still seem a bit unclear to me. Will Deacon has nicely explained what they represent in
http://lists.infradead.org/pipermail/linux-arm-kernel/2014-December/310816.html.
The IOMMU core doesn't make groups
mandatory, but requires them in some code paths.

For example the coldplug device add function add_iommu_group() called for all devices already registered when bus_set_iommu() is called will try to warn of devices added multiple times with a WARN_ON(dev->iommu_group). Another example is the iommu_bus_notifier() function which will call the remove_device() operation only when dev->iommu_group isn't NULL.

Quoted 3 lines

I'm thus unsure whether groups should be made mandatory, or whether the IOMMU core should be fixed to make them really optional (or, third option, whether there's something I haven't understood properly).

My plan is to make IOMMU groups mandatory. I am currently preparing and RFC patch-set to introduce default-domains (which will be per group). So when all IOMMU drivers are converted to make use of default domains the iommu groups will be mandatory.

Joerg

#17 lore raw

PATCH v5 11/18 iommu: exynos: remove useless device_add/remove callbacks

Quoted 13 lines · Joerg Roedel
Quoted 12 lines · Laurent Pinchart

IOMMU groups still seem a bit unclear to me. Will Deacon has nicely explained what they represent in
http://lists.infradead.org/pipermail/linux-arm-kernel/2014-December/310816.html.
The IOMMU core doesn't make groups
mandatory, but requires them in some code paths.

For example the coldplug device add function add_iommu_group() called for all devices already registered when bus_set_iommu() is called will try to warn of devices added multiple times with a WARN_ON(dev->iommu_group). Another example is the iommu_bus_notifier() function which will call the remove_device() operation only when dev->iommu_group isn't NULL.

Quoted 8 lines
Quoted 3 lines

I'm thus unsure whether groups should be made mandatory, or whether the IOMMU core should be fixed to make them really optional (or, third option, whether there's something I haven't understood properly).

My plan is to make IOMMU groups mandatory. I am currently preparing and RFC patch-set to introduce default-domains (which will be per group). So when all IOMMU drivers are converted to make use of default domains the iommu groups will be mandatory.

That makes sense to me, too. I think we should also consider extending the generic IOMMU device-tree binding to describe groups so that they can be instantiated by core code, without each driver having to work things out for itself.

Will

author maintainer
#18 lore raw

PATCH v5 11/18 iommu: exynos: remove useless device_add/remove callbacks

In reply to Joerg Roedel

Hello,

Quoted 15 lines · Joerg Roedel

Hi Laurent,

Quoted 12 lines · Laurent Pinchart

IOMMU groups still seem a bit unclear to me. Will Deacon has nicely explained what they represent in
http://lists.infradead.org/pipermail/linux-arm-kernel/2014-December/310816.html.
The IOMMU core doesn't make groups
mandatory, but requires them in some code paths.

For example the coldplug device add function add_iommu_group() called for all devices already registered when bus_set_iommu() is called will try to warn of devices added multiple times with a WARN_ON(dev->iommu_group). Another example is the iommu_bus_notifier() function which will call the remove_device() operation only when dev->iommu_group isn't NULL.

Quoted 7 lines
Quoted 3 lines

I'm thus unsure whether groups should be made mandatory, or whether the IOMMU core should be fixed to make them really optional (or, third option, whether there's something I haven't understood properly).

My plan is to make IOMMU groups mandatory. I am currently preparing and RFC patch-set to introduce default-domains (which will be per group). So when all IOMMU drivers are converted to make use of default domains the iommu groups will be mandatory.

Thanks for the comment, I will implement all that will be needed for it to exynos
iommu driver, but I would like to ask if you plan to merge my existing patches for
exynos iommu driver to your tree?

Best regards

Signature · 2 lines
Marek Szyprowski, PhD
Samsung R&D Institute Poland
#19 lore raw

PATCH v5 11/18 iommu: exynos: remove useless device_add/remove callbacks

In reply to Joerg Roedel

Hi Joerg,

Quoted 15 lines · On Monday 26 January 2015 12:00:59 Joerg Roedel wrote:

Hi Laurent,

Quoted 12 lines · Laurent Pinchart

IOMMU groups still seem a bit unclear to me. Will Deacon has nicely explained what they represent in
http://lists.infradead.org/pipermail/linux-arm-kernel/2014-December/310816
.html. The IOMMU core doesn't make groups
mandatory, but requires them in some code paths.

For example the coldplug device add function add_iommu_group() called for all devices already registered when bus_set_iommu() is called will try to warn of devices added multiple times with a WARN_ON(dev->iommu_group). Another example is the iommu_bus_notifier() function which will call the remove_device() operation only when dev->iommu_group isn't NULL.

Quoted 8 lines
Quoted 3 lines

I'm thus unsure whether groups should be made mandatory, or whether the IOMMU core should be fixed to make them really optional (or, third option, whether there's something I haven't understood properly).

My plan is to make IOMMU groups mandatory. I am currently preparing and RFC patch-set to introduce default-domains (which will be per group). So when all IOMMU drivers are converted to make use of default domains the iommu groups will be mandatory.

Could the default domain policy be configured by the IOMMU driver ? The ipmmu- vmsa driver supports four domains only, and serves up to 32 masters, with one group per master. A default of one domain per group wouldn't be usable.

Signature · 3 lines
Regards,

Laurent Pinchart
maintainer
#20 lore raw

PATCH v5 11/18 iommu: exynos: remove useless device_add/remove callbacks

Hi Laurent,

Quoted 9 lines · Laurent Pinchart
Quoted 4 lines · On Monday 26 January 2015 12:00:59 Joerg Roedel wrote:

My plan is to make IOMMU groups mandatory. I am currently preparing and RFC patch-set to introduce default-domains (which will be per group). So when all IOMMU drivers are converted to make use of default domains the iommu groups will be mandatory.

Could the default domain policy be configured by the IOMMU driver ? The ipmmu- vmsa driver supports four domains only, and serves up to 32 masters, with one group per master. A default of one domain per group wouldn't be usable.

I guess this limitation is a property of the iommu hardware. I currently have no support for this in the patch-set, but I think it is easy (and the best way) to support a model where we have only one default domain for all groups. This is not in the patch set right now, but will be added at some point.

Joerg

author maintainer
#21 lore raw

PATCH v5 12/18 iommu: exynos: add support for binding more than one sysmmu to master device

In reply to Marek Szyprowski

This patch adds support for assigning more than one SYSMMU controller to the master device. This has been achieved simply by chaning the struct device pointer in struct exynos_iommu_owner into the list of struct sysmmu_drvdata of all controllers assigned to the given master device.

---
 drivers/iommu/exynos-iommu.c | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)
drivers/iommu/exynos-iommu.c +5 -6
index e40e699..c6cca44 100644
@@ -186,7 +186,7 @@ static char *sysmmu_fault_name[SYSMMU_FAULTS_NUM] = {
 
 /* attached to dev.archdata.iommu of the master device */
 struct exynos_iommu_owner {
-	struct device *sysmmu;
+	struct list_head clients;
 };
 
 struct exynos_iommu_domain {
@@ -207,6 +207,7 @@ struct sysmmu_drvdata {
 	spinlock_t lock;
 	struct iommu_domain *domain;
 	struct list_head domain_node;
+	struct list_head owner_node;
 	phys_addr_t pgtable;
 	int version;
 };
@@ -693,8 +694,7 @@ static int exynos_iommu_attach_device(struct iommu_domain *domain,
 	if (!has_sysmmu(dev))
 		return -ENODEV;
 
-	data = dev_get_drvdata(owner->sysmmu);
-	if (data) {
+	list_for_each_entry(data, &owner->clients, owner_node) {
 		ret = __sysmmu_enable(data, pagetable, domain);
 		if (ret >= 0) {
 			data->master = dev;
@@ -722,7 +722,7 @@ static void exynos_iommu_detach_device(struct iommu_domain *domain,
 {
 	struct exynos_iommu_domain *priv = domain->priv;
 	phys_addr_t pagetable = virt_to_phys(priv->pgtable);
-	struct sysmmu_drvdata *data;
+	struct sysmmu_drvdata *data, *next;
 	unsigned long flags;
 	int found = 0;
 
@@ -730,14 +730,13 @@ static void exynos_iommu_detach_device(struct iommu_domain *domain,
 		return;
 
 	spin_lock_irqsave(&priv->lock, flags);
-	list_for_each_entry(data, &priv->clients, domain_node) {
+	list_for_each_entry_safe(data, next, &priv->clients, domain_node) {
 		if (data->master == dev) {
 			if (__sysmmu_disable(data)) {
 				data->master = NULL;
 				list_del_init(&data->domain_node);
 			}
 			found = true;
-			break;
 		}
 	}
 	spin_unlock_irqrestore(&priv->lock, flags);
Signature · 1 line
1.9.2
author maintainer
#22 lore raw

PATCH v5 13/18 iommu: exynos: add support for runtime_pm

In reply to Marek Szyprowski

This patch fixes support for runtime power management for SYSMMU controllers, so they are enabled when master device is attached.

---
 drivers/iommu/exynos-iommu.c | 2 ++
 1 file changed, 2 insertions(+)
drivers/iommu/exynos-iommu.c +2 -0
index c6cca44..f8609f4 100644
@@ -695,6 +695,7 @@ static int exynos_iommu_attach_device(struct iommu_domain *domain,
 		return -ENODEV;
 
 	list_for_each_entry(data, &owner->clients, owner_node) {
+		pm_runtime_get_sync(data->sysmmu);
 		ret = __sysmmu_enable(data, pagetable, domain);
 		if (ret >= 0) {
 			data->master = dev;
@@ -736,6 +737,7 @@ static void exynos_iommu_detach_device(struct iommu_domain *domain,
 				data->master = NULL;
 				list_del_init(&data->domain_node);
 			}
+			pm_runtime_put(data->sysmmu);
 			found = true;
 		}
 	}
Signature · 1 line
1.9.2
author maintainer
#23 lore raw

PATCH v5 14/18 iommu: exynos: rename variables to reflect their purpose

In reply to Marek Szyprowski

This patch renames some variables to make the code easier to understand. 'domain' is replaced by 'iommu_domain' (more generic entity) and really meaning less 'priv' by 'domain' to reflect its purpose.

---
 drivers/iommu/exynos-iommu.c | 191 ++++++++++++++++++++++---------------------
 1 file changed, 97 insertions(+), 94 deletions(-)
drivers/iommu/exynos-iommu.c +97 -94
index f8609f4..78a12ea 100644
@@ -430,8 +430,8 @@ static void __sysmmu_enable_nocount(struct sysmmu_drvdata *data)
 		clk_disable(data->clk_master);
 }
 
-static int __sysmmu_enable(struct sysmmu_drvdata *data,
-			phys_addr_t pgtable, struct iommu_domain *domain)
+static int __sysmmu_enable(struct sysmmu_drvdata *data, phys_addr_t pgtable,
+			   struct iommu_domain *iommu_domain)
 {
 	int ret = 0;
 	unsigned long flags;
@@ -439,7 +439,7 @@ static int __sysmmu_enable(struct sysmmu_drvdata *data,
 	spin_lock_irqsave(&data->lock, flags);
 	if (set_sysmmu_active(data)) {
 		data->pgtable = pgtable;
-		data->domain = domain;
+		data->domain = iommu_domain;
 
 		__sysmmu_enable_nocount(data);
 
@@ -602,92 +602,93 @@ static inline void pgtable_flush(void *vastart, void *vaend)
 				virt_to_phys(vaend));
 }
 
-static int exynos_iommu_domain_init(struct iommu_domain *domain)
+static int exynos_iommu_domain_init(struct iommu_domain *iommu_domain)
 {
-	struct exynos_iommu_domain *priv;
+	struct exynos_iommu_domain *domain;
 	int i;
 
-	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
-	if (!priv)
+	domain = kzalloc(sizeof(*domain), GFP_KERNEL);
+	if (!domain)
 		return -ENOMEM;
 
-	priv->pgtable = (sysmmu_pte_t *)__get_free_pages(GFP_KERNEL, 2);
-	if (!priv->pgtable)
+	domain->pgtable = (sysmmu_pte_t *)__get_free_pages(GFP_KERNEL, 2);
+	if (!domain->pgtable)
 		goto err_pgtable;
 
-	priv->lv2entcnt = (short *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 1);
-	if (!priv->lv2entcnt)
+	domain->lv2entcnt = (short *)
+			    __get_free_pages(GFP_KERNEL | __GFP_ZERO, 1);
+	if (!domain->lv2entcnt)
 		goto err_counter;
 
 	/* Workaround for System MMU v3.3 to prevent caching 1MiB mapping */
 	for (i = 0; i < NUM_LV1ENTRIES; i += 8) {
-		priv->pgtable[i + 0] = ZERO_LV2LINK;
-		priv->pgtable[i + 1] = ZERO_LV2LINK;
-		priv->pgtable[i + 2] = ZERO_LV2LINK;
-		priv->pgtable[i + 3] = ZERO_LV2LINK;
-		priv->pgtable[i + 4] = ZERO_LV2LINK;
-		priv->pgtable[i + 5] = ZERO_LV2LINK;
-		priv->pgtable[i + 6] = ZERO_LV2LINK;
-		priv->pgtable[i + 7] = ZERO_LV2LINK;
+		domain->pgtable[i + 0] = ZERO_LV2LINK;
+		domain->pgtable[i + 1] = ZERO_LV2LINK;
+		domain->pgtable[i + 2] = ZERO_LV2LINK;
+		domain->pgtable[i + 3] = ZERO_LV2LINK;
+		domain->pgtable[i + 4] = ZERO_LV2LINK;
+		domain->pgtable[i + 5] = ZERO_LV2LINK;
+		domain->pgtable[i + 6] = ZERO_LV2LINK;
+		domain->pgtable[i + 7] = ZERO_LV2LINK;
 	}
 
-	pgtable_flush(priv->pgtable, priv->pgtable + NUM_LV1ENTRIES);
+	pgtable_flush(domain->pgtable, domain->pgtable + NUM_LV1ENTRIES);
 
-	spin_lock_init(&priv->lock);
-	spin_lock_init(&priv->pgtablelock);
-	INIT_LIST_HEAD(&priv->clients);
+	spin_lock_init(&domain->lock);
+	spin_lock_init(&domain->pgtablelock);
+	INIT_LIST_HEAD(&domain->clients);
 
-	domain->geometry.aperture_start = 0;
-	domain->geometry.aperture_end   = ~0UL;
-	domain->geometry.force_aperture = true;
+	iommu_domain->geometry.aperture_start = 0;
+	iommu_domain->geometry.aperture_end   = ~0UL;
+	iommu_domain->geometry.force_aperture = true;
 
-	domain->priv = priv;
+	iommu_domain->priv = domain;
 	return 0;
 
 err_counter:
-	free_pages((unsigned long)priv->pgtable, 2);
+	free_pages((unsigned long)domain->pgtable, 2);
 err_pgtable:
-	kfree(priv);
+	kfree(domain);
 	return -ENOMEM;
 }
 
-static void exynos_iommu_domain_destroy(struct iommu_domain *domain)
+static void exynos_iommu_domain_destroy(struct iommu_domain *iommu_domain)
 {
-	struct exynos_iommu_domain *priv = domain->priv;
+	struct exynos_iommu_domain *domain = iommu_domain->priv;
 	struct sysmmu_drvdata *data;
 	unsigned long flags;
 	int i;
 
-	WARN_ON(!list_empty(&priv->clients));
+	WARN_ON(!list_empty(&domain->clients));
 
-	spin_lock_irqsave(&priv->lock, flags);
+	spin_lock_irqsave(&domain->lock, flags);
 
-	list_for_each_entry(data, &priv->clients, domain_node) {
+	list_for_each_entry(data, &domain->clients, domain_node) {
 		if (__sysmmu_disable(data))
 			data->master = NULL;
 		list_del_init(&data->domain_node);
 	}
 
-	spin_unlock_irqrestore(&priv->lock, flags);
+	spin_unlock_irqrestore(&domain->lock, flags);
 
 	for (i = 0; i < NUM_LV1ENTRIES; i++)
-		if (lv1ent_page(priv->pgtable + i))
+		if (lv1ent_page(domain->pgtable + i))
 			kmem_cache_free(lv2table_kmem_cache,
-				phys_to_virt(lv2table_base(priv->pgtable + i)));
+			      phys_to_virt(lv2table_base(domain->pgtable + i)));
 
-	free_pages((unsigned long)priv->pgtable, 2);
-	free_pages((unsigned long)priv->lv2entcnt, 1);
-	kfree(domain->priv);
-	domain->priv = NULL;
+	free_pages((unsigned long)domain->pgtable, 2);
+	free_pages((unsigned long)domain->lv2entcnt, 1);
+	kfree(iommu_domain->priv);
+	iommu_domain->priv = NULL;
 }
 
-static int exynos_iommu_attach_device(struct iommu_domain *domain,
+static int exynos_iommu_attach_device(struct iommu_domain *iommu_domain,
 				   struct device *dev)
 {
 	struct exynos_iommu_owner *owner = dev->archdata.iommu;
-	struct exynos_iommu_domain *priv = domain->priv;
+	struct exynos_iommu_domain *domain = iommu_domain->priv;
 	struct sysmmu_drvdata *data;
-	phys_addr_t pagetable = virt_to_phys(priv->pgtable);
+	phys_addr_t pagetable = virt_to_phys(domain->pgtable);
 	unsigned long flags;
 	int ret = -ENODEV;
 
@@ -696,13 +697,13 @@ static int exynos_iommu_attach_device(struct iommu_domain *domain,
 
 	list_for_each_entry(data, &owner->clients, owner_node) {
 		pm_runtime_get_sync(data->sysmmu);
-		ret = __sysmmu_enable(data, pagetable, domain);
+		ret = __sysmmu_enable(data, pagetable, iommu_domain);
 		if (ret >= 0) {
 			data->master = dev;
 
-			spin_lock_irqsave(&priv->lock, flags);
-			list_add_tail(&data->domain_node, &priv->clients);
-			spin_unlock_irqrestore(&priv->lock, flags);
+			spin_lock_irqsave(&domain->lock, flags);
+			list_add_tail(&data->domain_node, &domain->clients);
+			spin_unlock_irqrestore(&domain->lock, flags);
 		}
 	}
 
@@ -718,11 +719,11 @@ static int exynos_iommu_attach_device(struct iommu_domain *domain,
 	return ret;
 }
 
-static void exynos_iommu_detach_device(struct iommu_domain *domain,
+static void exynos_iommu_detach_device(struct iommu_domain *iommu_domain,
 				    struct device *dev)
 {
-	struct exynos_iommu_domain *priv = domain->priv;
-	phys_addr_t pagetable = virt_to_phys(priv->pgtable);
+	struct exynos_iommu_domain *domain = iommu_domain->priv;
+	phys_addr_t pagetable = virt_to_phys(domain->pgtable);
 	struct sysmmu_drvdata *data, *next;
 	unsigned long flags;
 	int found = 0;
@@ -730,8 +731,8 @@ static void exynos_iommu_detach_device(struct iommu_domain *domain,
 	if (!has_sysmmu(dev))
 		return;
 
-	spin_lock_irqsave(&priv->lock, flags);
-	list_for_each_entry_safe(data, next, &priv->clients, domain_node) {
+	spin_lock_irqsave(&domain->lock, flags);
+	list_for_each_entry_safe(data, next, &domain->clients, domain_node) {
 		if (data->master == dev) {
 			if (__sysmmu_disable(data)) {
 				data->master = NULL;
@@ -741,7 +742,7 @@ static void exynos_iommu_detach_device(struct iommu_domain *domain,
 			found = true;
 		}
 	}
-	spin_unlock_irqrestore(&priv->lock, flags);
+	spin_unlock_irqrestore(&domain->lock, flags);
 
 	if (found)
 		dev_dbg(dev, "%s: Detached IOMMU with pgtable %pa\n",
@@ -750,7 +751,7 @@ static void exynos_iommu_detach_device(struct iommu_domain *domain,
 		dev_err(dev, "%s: No IOMMU is attached\n", __func__);
 }
 
-static sysmmu_pte_t *alloc_lv2entry(struct exynos_iommu_domain *priv,
+static sysmmu_pte_t *alloc_lv2entry(struct exynos_iommu_domain *domain,
 		sysmmu_pte_t *sent, sysmmu_iova_t iova, short *pgcounter)
 {
 	if (lv1ent_section(sent)) {
@@ -792,17 +793,17 @@ static sysmmu_pte_t *alloc_lv2entry(struct exynos_iommu_domain *priv,
 		if (need_flush_flpd_cache) {
 			struct sysmmu_drvdata *data;
 
-			spin_lock(&priv->lock);
-			list_for_each_entry(data, &priv->clients, domain_node)
+			spin_lock(&domain->lock);
+			list_for_each_entry(data, &domain->clients, domain_node)
 				sysmmu_tlb_invalidate_flpdcache(data, iova);
-			spin_unlock(&priv->lock);
+			spin_unlock(&domain->lock);
 		}
 	}
 
 	return page_entry(sent, iova);
 }
 
-static int lv1set_section(struct exynos_iommu_domain *priv,
+static int lv1set_section(struct exynos_iommu_domain *domain,
 			  sysmmu_pte_t *sent, sysmmu_iova_t iova,
 			  phys_addr_t paddr, short *pgcnt)
 {
@@ -827,17 +828,17 @@ static int lv1set_section(struct exynos_iommu_domain *priv,
 
 	pgtable_flush(sent, sent + 1);
 
-	spin_lock(&priv->lock);
+	spin_lock(&domain->lock);
 	if (lv1ent_page_zero(sent)) {
 		struct sysmmu_drvdata *data;
 		/*
 		 * Flushing FLPD cache in System MMU v3.3 that may cache a FLPD
 		 * entry by speculative prefetch of SLPD which has no mapping.
 		 */
-		list_for_each_entry(data, &priv->clients, domain_node)
+		list_for_each_entry(data, &domain->clients, domain_node)
 			sysmmu_tlb_invalidate_flpdcache(data, iova);
 	}
-	spin_unlock(&priv->lock);
+	spin_unlock(&domain->lock);
 
 	return 0;
 }
@@ -897,74 +898,76 @@ static int lv2set_page(sysmmu_pte_t *pent, phys_addr_t paddr, size_t size,
  *   than or equal to 128KiB.
  * - Start address of an I/O virtual region must be aligned by 128KiB.
  */
-static int exynos_iommu_map(struct iommu_domain *domain, unsigned long l_iova,
-			 phys_addr_t paddr, size_t size, int prot)
+static int exynos_iommu_map(struct iommu_domain *iommu_domain,
+			unsigned long l_iova, phys_addr_t paddr, size_t size,
+			int prot)
 {
-	struct exynos_iommu_domain *priv = domain->priv;
+	struct exynos_iommu_domain *domain = iommu_domain->priv;
 	sysmmu_pte_t *entry;
 	sysmmu_iova_t iova = (sysmmu_iova_t)l_iova;
 	unsigned long flags;
 	int ret = -ENOMEM;
 
-	BUG_ON(priv->pgtable == NULL);
+	BUG_ON(domain->pgtable == NULL);
 
-	spin_lock_irqsave(&priv->pgtablelock, flags);
+	spin_lock_irqsave(&domain->pgtablelock, flags);
 
-	entry = section_entry(priv->pgtable, iova);
+	entry = section_entry(domain->pgtable, iova);
 
 	if (size == SECT_SIZE) {
-		ret = lv1set_section(priv, entry, iova, paddr,
-					&priv->lv2entcnt[lv1ent_offset(iova)]);
+		ret = lv1set_section(domain, entry, iova, paddr,
+				     &domain->lv2entcnt[lv1ent_offset(iova)]);
 	} else {
 		sysmmu_pte_t *pent;
 
-		pent = alloc_lv2entry(priv, entry, iova,
-					&priv->lv2entcnt[lv1ent_offset(iova)]);
+		pent = alloc_lv2entry(domain, entry, iova,
+				      &domain->lv2entcnt[lv1ent_offset(iova)]);
 
 		if (IS_ERR(pent))
 			ret = PTR_ERR(pent);
 		else
 			ret = lv2set_page(pent, paddr, size,
-					&priv->lv2entcnt[lv1ent_offset(iova)]);
+				       &domain->lv2entcnt[lv1ent_offset(iova)]);
 	}
 
 	if (ret)
 		pr_err("%s: Failed(%d) to map %#zx bytes @ %#x\n",
 			__func__, ret, size, iova);
 
-	spin_unlock_irqrestore(&priv->pgtablelock, flags);
+	spin_unlock_irqrestore(&domain->pgtablelock, flags);
 
 	return ret;
 }
 
-static void exynos_iommu_tlb_invalidate_entry(struct exynos_iommu_domain *priv,
-						sysmmu_iova_t iova, size_t size)
+static
+void exynos_iommu_tlb_invalidate_entry(struct exynos_iommu_domain *domain,
+					sysmmu_iova_t iova, size_t size)
 {
 	struct sysmmu_drvdata *data;
 	unsigned long flags;
 
-	spin_lock_irqsave(&priv->lock, flags);
+	spin_lock_irqsave(&domain->lock, flags);
 
-	list_for_each_entry(data, &priv->clients, domain_node)
+	list_for_each_entry(data, &domain->clients, domain_node)
 		sysmmu_tlb_invalidate_entry(data, iova, size);
 
-	spin_unlock_irqrestore(&priv->lock, flags);
+	spin_unlock_irqrestore(&domain->lock, flags);
 }
 
-static size_t exynos_iommu_unmap(struct iommu_domain *domain,
+static size_t exynos_iommu_unmap(struct iommu_domain *iommu_domain,
 					unsigned long l_iova, size_t size)
 {
-	struct exynos_iommu_domain *priv = domain->priv;
+	struct exynos_iommu_domain *domain = iommu_domain->priv;
 	sysmmu_iova_t iova = (sysmmu_iova_t)l_iova;
 	sysmmu_pte_t *ent;
 	size_t err_pgsize;
 	unsigned long flags;
 
-	BUG_ON(priv->pgtable == NULL);
+	BUG_ON(domain->pgtable == NULL);
 
-	spin_lock_irqsave(&priv->pgtablelock, flags);
+	spin_lock_irqsave(&domain->pgtablelock, flags);
 
-	ent = section_entry(priv->pgtable, iova);
+	ent = section_entry(domain->pgtable, iova);
 
 	if (lv1ent_section(ent)) {
 		if (WARN_ON(size < SECT_SIZE)) {
@@ -998,7 +1001,7 @@ static size_t exynos_iommu_unmap(struct iommu_domain *domain,
 		*ent = 0;
 		size = SPAGE_SIZE;
 		pgtable_flush(ent, ent + 1);
-		priv->lv2entcnt[lv1ent_offset(iova)] += 1;
+		domain->lv2entcnt[lv1ent_offset(iova)] += 1;
 		goto done;
 	}
 
@@ -1012,15 +1015,15 @@ static size_t exynos_iommu_unmap(struct iommu_domain *domain,
 	pgtable_flush(ent, ent + SPAGES_PER_LPAGE);
 
 	size = LPAGE_SIZE;
-	priv->lv2entcnt[lv1ent_offset(iova)] += SPAGES_PER_LPAGE;
+	domain->lv2entcnt[lv1ent_offset(iova)] += SPAGES_PER_LPAGE;
 done:
-	spin_unlock_irqrestore(&priv->pgtablelock, flags);
+	spin_unlock_irqrestore(&domain->pgtablelock, flags);
 
-	exynos_iommu_tlb_invalidate_entry(priv, iova, size);
+	exynos_iommu_tlb_invalidate_entry(domain, iova, size);
 
 	return size;
 err:
-	spin_unlock_irqrestore(&priv->pgtablelock, flags);
+	spin_unlock_irqrestore(&domain->pgtablelock, flags);
 
 	pr_err("%s: Failed: size(%#zx) @ %#x is smaller than page size %#zx\n",
 		__func__, size, iova, err_pgsize);
@@ -1028,17 +1031,17 @@ err:
 	return 0;
 }
 
-static phys_addr_t exynos_iommu_iova_to_phys(struct iommu_domain *domain,
+static phys_addr_t exynos_iommu_iova_to_phys(struct iommu_domain *iommu_domain,
 					  dma_addr_t iova)
 {
-	struct exynos_iommu_domain *priv = domain->priv;
+	struct exynos_iommu_domain *domain = iommu_domain->priv;
 	sysmmu_pte_t *entry;
 	unsigned long flags;
 	phys_addr_t phys = 0;
 
-	spin_lock_irqsave(&priv->pgtablelock, flags);
+	spin_lock_irqsave(&domain->pgtablelock, flags);
 
-	entry = section_entry(priv->pgtable, iova);
+	entry = section_entry(domain->pgtable, iova);
 
 	if (lv1ent_section(entry)) {
 		phys = section_phys(entry) + section_offs(iova);
@@ -1051,7 +1054,7 @@ static phys_addr_t exynos_iommu_iova_to_phys(struct iommu_domain *domain,
 			phys = spage_phys(entry) + spage_offs(iova);
 	}
 
-	spin_unlock_irqrestore(&priv->pgtablelock, flags);
+	spin_unlock_irqrestore(&domain->pgtablelock, flags);
 
 	return phys;
 }
Signature · 1 line
1.9.2
author maintainer
#24 lore raw

PATCH v5 15/18 iommu: exynos: document internal structures

In reply to Marek Szyprowski

Add a few words of comment to all internal structures used by the driver.

---
 drivers/iommu/exynos-iommu.c | 49 +++++++++++++++++++++++++++++---------------
 1 file changed, 33 insertions(+), 16 deletions(-)
drivers/iommu/exynos-iommu.c +33 -16
index 78a12ea..ef71725 100644
@@ -184,32 +184,49 @@ static char *sysmmu_fault_name[SYSMMU_FAULTS_NUM] = {
 	"UNKNOWN FAULT"
 };
 
-/* attached to dev.archdata.iommu of the master device */
+/*
+ * This structure is attached to dev.archdata.iommu of the master device
+ * on device add, contains a list of SYSMMU controllers defined by device tree,
+ * which are bound to given master device. It is usually referenced by 'owner'
+ * pointer.
+ */
 struct exynos_iommu_owner {
-	struct list_head clients;
+	struct list_head clients; /* list of sysmmu_drvdata.owner_node */
 };
 
+/*
+ * This structure is stored in ->priv field of generic struct iommu_domain,
+ * contains list of SYSMMU controllers from all master devices, which has been
+ * attached to this domain and page tables of IO address space defined by this
+ * domain. It is usually referenced by 'domain' pointer.
+ */
 struct exynos_iommu_domain {
-	struct list_head clients; /* list of sysmmu_drvdata.node */
+	struct list_head clients; /* list of sysmmu_drvdata.domain_node */
 	sysmmu_pte_t *pgtable; /* lv1 page table, 16KB */
 	short *lv2entcnt; /* free lv2 entry counter for each section */
-	spinlock_t lock; /* lock for this structure */
+	spinlock_t lock; /* lock for modyfying list of clients */
 	spinlock_t pgtablelock; /* lock for modifying page table @ pgtable */
 };
 
+/*
+ * This structure hold all data of a single SYSMMU controller, this includes
+ * hw resources like registers and clocks, pointers and list nodes to connect
+ * it to all other structures, internal state and parameters read from device
+ * tree. It is usually referenced by 'data' pointer.
+ */
 struct sysmmu_drvdata {
-	struct device *sysmmu;	/* System MMU's device descriptor */
-	struct device *master;	/* Owner of system MMU */
-	void __iomem *sfrbase;
-	struct clk *clk;
-	struct clk *clk_master;
-	int activations;
-	spinlock_t lock;
-	struct iommu_domain *domain;
-	struct list_head domain_node;
-	struct list_head owner_node;
-	phys_addr_t pgtable;
-	int version;
+	struct device *sysmmu; /* SYSMMU controller device */
+	struct device *master; /* master device (owner of given SYSMMU) */
+	void __iomem *sfrbase; /* our registers */
+	struct clk *clk; /* SYSMMU's clock */
+	struct clk *clk_master; /* master's device clock */
+	int activations; /* number of calls to sysmmu_enable */
+	spinlock_t lock; /* lock for modyfying enable/disable state */
+	struct iommu_domain *domain; /* domain we belong to */
+	struct list_head domain_node; /* node for domain clients list */
+	struct list_head owner_node; /* node for owner clients list */
+	phys_addr_t pgtable; /* assigned page table structure */
+	int version; /* our version */
 };
 
 static bool set_sysmmu_active(struct sysmmu_drvdata *data)
Signature · 1 line
1.9.2
author maintainer
#25 lore raw

PATCH v5 16/18 iommu: exynos: remove excessive includes and sort others alphabetically

In reply to Marek Szyprowski

Removed following unused includes: <linux/mm.h>, <linux/errno.h>, <linux/memblock.h> and <linux/export.h>.

---
 drivers/iommu/exynos-iommu.c | 14 +++++---------
 1 file changed, 5 insertions(+), 9 deletions(-)
drivers/iommu/exynos-iommu.c +5 -9
index ef71725..c53cc8f 100644
@@ -12,19 +12,15 @@
 #define DEBUG
 #endif
 
-#include <linux/io.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/pm_runtime.h>
 #include <linux/clk.h>
 #include <linux/err.h>
-#include <linux/mm.h>
+#include <linux/io.h>
 #include <linux/iommu.h>
-#include <linux/errno.h>
+#include <linux/interrupt.h>
 #include <linux/list.h>
-#include <linux/memblock.h>
-#include <linux/export.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
 
 #include <asm/cacheflush.h>
 #include <asm/pgtable.h>
Signature · 1 line
1.9.2
author maintainer
#26 lore raw

PATCH v5 17/18 iommu: exynos: init from dt-specific callback instead of initcall

In reply to Marek Szyprowski

This patch introduces IOMMU_OF_DECLARE-based initialization to the driver, which replaces subsys_initcall-based procedure. exynos_iommu_of_setup ensures that each sysmmu controller is probed before its master device.

---
 drivers/iommu/exynos-iommu.c | 30 ++++++++++++++++++++++++++++--
 1 file changed, 28 insertions(+), 2 deletions(-)
drivers/iommu/exynos-iommu.c +28 -2
index c53cc8f..ff169ce 100644
@@ -13,16 +13,21 @@
 #endif
 
 #include <linux/clk.h>
+#include <linux/dma-mapping.h>
 #include <linux/err.h>
 #include <linux/io.h>
 #include <linux/iommu.h>
 #include <linux/interrupt.h>
 #include <linux/list.h>
+#include <linux/of.h>
+#include <linux/of_iommu.h>
+#include <linux/of_platform.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/slab.h>
 
 #include <asm/cacheflush.h>
+#include <asm/dma-iommu.h>
 #include <asm/pgtable.h>
 
 typedef u32 sysmmu_iova_t;
@@ -1072,7 +1077,7 @@ static phys_addr_t exynos_iommu_iova_to_phys(struct iommu_domain *iommu_domain,
 	return phys;
 }
 
-static const struct iommu_ops exynos_iommu_ops = {
+static struct iommu_ops exynos_iommu_ops = {
 	.domain_init = exynos_iommu_domain_init,
 	.domain_destroy = exynos_iommu_domain_destroy,
 	.attach_dev = exynos_iommu_attach_device,
@@ -1084,6 +1089,8 @@ static const struct iommu_ops exynos_iommu_ops = {
 	.pgsize_bitmap = SECT_SIZE | LPAGE_SIZE | SPAGE_SIZE,
 };
 
+static int init_done;
+
 static int __init exynos_iommu_init(void)
 {
 	int ret;
@@ -1116,6 +1123,8 @@ static int __init exynos_iommu_init(void)
 		goto err_set_iommu;
 	}
 
+	init_done = true;
+
 	return 0;
 err_set_iommu:
 	kmem_cache_free(lv2table_kmem_cache, zero_lv2_table);
@@ -1125,4 +1134,21 @@ err_reg_driver:
 	kmem_cache_destroy(lv2table_kmem_cache);
 	return ret;
 }
-subsys_initcall(exynos_iommu_init);
+
+static int __init exynos_iommu_of_setup(struct device_node *np)
+{
+	struct platform_device *pdev;
+
+	if (!init_done)
+		exynos_iommu_init();
+
+	pdev = of_platform_device_create(np, NULL, platform_bus_type.dev_root);
+	if (IS_ERR(pdev))
+		return PTR_ERR(pdev);
+
+	of_iommu_set_ops(np, &exynos_iommu_ops);
+	return 0;
+}
+
+IOMMU_OF_DECLARE(exynos_iommu_of, "samsung,exynos-sysmmu",
+		 exynos_iommu_of_setup);
Signature · 1 line
1.9.2
author maintainer
#27 lore raw

PATCH v5 18/18 iommu: exynos: add callback for initializing devices from device tree

In reply to Marek Szyprowski

This patch adds implementation of of_xlate callback, which prepares masters device for attaching to IOMMU. This callback is called during creating devices from device tree.

---
 drivers/iommu/exynos-iommu.c | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)
drivers/iommu/exynos-iommu.c +28 -0
index ff169ce..99217f7 100644
@@ -1077,6 +1077,33 @@ static phys_addr_t exynos_iommu_iova_to_phys(struct iommu_domain *iommu_domain,
 	return phys;
 }
 
+static int exynos_iommu_of_xlate(struct device *dev,
+				 struct of_phandle_args *spec)
+{
+	struct exynos_iommu_owner *owner = dev->archdata.iommu;
+	struct platform_device *sysmmu = of_find_device_by_node(spec->np);
+	struct sysmmu_drvdata *data;
+
+	if (!sysmmu)
+		return -ENODEV;
+
+	data = platform_get_drvdata(sysmmu);
+	if (!data)
+		return -ENODEV;
+
+	if (!owner) {
+		owner = kzalloc(sizeof(*owner), GFP_KERNEL);
+		if (!owner)
+			return -ENOMEM;
+
+		INIT_LIST_HEAD(&owner->clients);
+		dev->archdata.iommu = owner;
+	}
+
+	list_add_tail(&data->owner_node, &owner->clients);
+	return 0;
+}
+
 static struct iommu_ops exynos_iommu_ops = {
 	.domain_init = exynos_iommu_domain_init,
 	.domain_destroy = exynos_iommu_domain_destroy,
@@ -1087,6 +1114,7 @@ static struct iommu_ops exynos_iommu_ops = {
 	.map_sg = default_iommu_map_sg,
 	.iova_to_phys = exynos_iommu_iova_to_phys,
 	.pgsize_bitmap = SECT_SIZE | LPAGE_SIZE | SPAGE_SIZE,
+	.of_xlate = exynos_iommu_of_xlate,
 };
 
 static int init_done;
Signature · 1 line
1.9.2
#28 lore raw

v5 cover Exynos SYSMMU (IOMMU) integration with DT and DMA-mapping subsystem

In reply to Marek Szyprowski

Hi Marek,
This is patch set against v3.19-rc4 plus 'Add HDMI support for Exynos5420 platform', right?
No other dependencies? If there is, do you have a public git tree to be cloned?

Thanks.

Quoted 114 lines · Marek Szyprowski

Hello Everyone,

This is yet another attempt to get Exynos SYSMMU driver with integrated with IOMMU & DMA-mapping subsystems. The main change from previous version is a rebase onto some more pending Exynos DTS patches and minor fixes of the reported issues.

Merge plan for this patchset:

1. All iommu related patches (with 'iommu: exynos') can be merged to iommu tree. They don't have any direct dependencies on the DTS, DRM and power domain initialization change - without them the driver will simply not initialize, when no exynos,sysmmu nodes are provided in device tree.

Joerg, could you merge those patches?

2. DTS and power domain patches should go to Samsung Exynos tree. Those patches depends on earlier DTS patches for Exynos SoCs, which make this patchset really complete:
- 'ARM: DTS: Exynos: convert to generic power domain bindings'
(http://www.spinics.net/lists/linux-samsung-soc/msg40584.html)
- '[PATCH v4 0/7] Enable HDMI support on Exynos platforms'
(http://www.spinics.net/lists/arm-kernel/msg391148.html)
- '[PATCH 0/2] Add HDMI support for Exynos5420 platform'
(http://www.spinics.net/lists/linux-samsung-soc/msg41364.html)

Kukjin, could you merge those patches?

3. Exynos DRM fix. This patch in my opinion should go Exynos DRM tree.

Inki, could you merge it?

Best regards
Marek Szyprowski
Samsung R&D Institute Poland

Changelog:

v5:
- rebased onto 'Add HDMI support for Exynos5420 platform' patchset
- fixed 'const' issue in 'iommu: exynos: init from dt-specific callback instead of initcall' patch, thanks to Tobias Jakobi for reporting it
- fixed copy-paste typo in exynos5250 dts patch

v4: http://www.spinics.net/lists/linux-samsung-soc/msg41177.html
- rebased onto v3.19-rc4 and other Exynos DTS queued patches
- added DTS patch for Exynos 5250 & 5420/5422/5800

v3: http://www.spinics.net/lists/linux-samsung-soc/msg39168.html
- rebased onto "[RFC PATCH v4 0/8] Introduce automatic DMA configuration for IOMMU masters"
- added some minor fixes for iommu and dma-mapping frameworks

v2: http://thread.gmane.org/gmane.linux.kernel.iommu/6472/
- rebased onto "[RFC PATCH v3 0/7] Introduce automatic DMA configuration for IOMMU masters" patches:
http://www.spinics.net/lists/arm-kernel/msg362076.html
- changed initialization from bus notifiers to DT related callbacks
- removed support for separate IO address spaces - this will be discussed separately after the basic support gets merged
- removed support for power domain notifier-based runtime power management - this also will be discussed separately later

v1: https://lkml.org/lkml/2014/8/5/183
- initial version, feature complete, completely rewrote integration approach

Patch summary:

Marek Szyprowski (18):
drm: exynos: detach from default dma-mapping domain on init
arm: exynos: pm_domains: add support for devices registered before
arch_initcall
ARM: dts: exynos4: add sysmmu nodes
ARM: dts: exynos5250: add sysmmu nodes
ARM: dts: exynos5420: add sysmmu nodes
iommu: exynos: don't read version register on every tlb operation
iommu: exynos: remove unused functions
iommu: exynos: remove useless spinlock
iommu: exynos: refactor function parameters to simplify code
iommu: exynos: remove unused functions, part 2
iommu: exynos: remove useless device_add/remove callbacks
iommu: exynos: add support for binding more than one sysmmu to master
device
iommu: exynos: add support for runtime_pm
iommu: exynos: rename variables to reflect their purpose
iommu: exynos: document internal structures
iommu: exynos: remove excessive includes and sort others
alphabetically
iommu: exynos: init from dt-specific callback instead of initcall
iommu: exynos: add callback for initializing devices from device tree

 arch/arm/boot/dts/exynos4.dtsi            | 118 +++++++
 arch/arm/boot/dts/exynos4210.dtsi         |  23 ++
 arch/arm/boot/dts/exynos4x12.dtsi         |  82 +++++
 arch/arm/boot/dts/exynos5250.dtsi         | 250 +++++++++++++++
 arch/arm/boot/dts/exynos5420.dtsi         | 181 +++++++++++
 arch/arm/mach-exynos/pm_domains.c         |   9 +-
 drivers/gpu/drm/exynos/exynos_drm_iommu.c |   3 +
 drivers/iommu/exynos-iommu.c              | 492 ++++++++++++++----------------
 8 files changed, 888 insertions(+), 270 deletions(-)

--
1.9.2

_______________________________________________
iommu mailing list
iommu at lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

author maintainer
#29 lore raw

v5 cover Exynos SYSMMU (IOMMU) integration with DT and DMA-mapping subsystem

Hello,

Quoted 3 lines · Hongbo Zhang

This is patch set against v3.19-rc4 plus 'Add HDMI support for Exynos5420 platform', right?
No other dependencies? If there is, do you have a public git tree to be cloned?

I've just prepared public branch based on v3.19-rc7 with kgene/v3.20-next/dt-samsung-3 branch merged and exynos-hdmi patches applied.

It is available here:
http://git.linaro.org/git-ro/people/marek.szyprowski/linux-srpol.git
v3.19-hdmi-iommu

Tested with Exynos5422-based Odroid XU3 and Exynos4412-based Odroid U3.

Best regards

Signature · 2 lines
Marek Szyprowski, PhD
Samsung R&D Institute Poland
maintainer
#30 lore raw

v5 cover Exynos SYSMMU (IOMMU) integration with DT and DMA-mapping subsystem

In reply to Marek Szyprowski

Hi Marek,

Quoted 6 lines · Marek Szyprowski

1. All iommu related patches (with 'iommu: exynos') can be merged to iommu tree. They don't have any direct dependencies on the DTS, DRM and power domain initialization change - without them the driver will simply not initialize, when no exynos,sysmmu nodes are provided in device tree.

Joerg, could you merge those patches?

Given the previous comments and tests on this patch set I am still waiting for some Acked-bys and/or Tested-bys on this. Can you collect these and resend then (probably after the v3.20 merge window)?

Joerg

#31 lore raw

v5 cover Exynos SYSMMU (IOMMU) integration with DT and DMA-mapping subsystem

Hello Marek,

Quoted 8 lines · Joerg Roedel

Hi Marek,

Quoted 5 lines · Marek Szyprowski

1. All iommu related patches (with 'iommu: exynos') can be merged to iommu tree. They don't have any direct dependencies on the DTS, DRM and power domain initialization change - without them the driver will simply not initialize, when no exynos,sysmmu nodes are provided in device tree.

Quoted 6 lines
Quoted 1 line

Joerg, could you merge those patches?

Given the previous comments and tests on this patch set I am still waiting for some Acked-bys and/or Tested-bys on this. Can you collect these and resend then (probably after the v3.20 merge window)?

I rebased your patches on top of latest linux-next (next-20150415) and tested it on my Exynos5420 Peach Pit. HDMI display is working correctly (both console and X) when CONFIG_DRM_EXYNOS_IOMMU is enabled. I also see that the mixer is attached to the IOMMU domain:

exynos-mixer 14450000.mixer: exynos_iommu_attach_device: Attached IOMMU with pgtable 0x6e5e0000
...
exynos-sysmmu 14650000.sysmmu: Enabled

As I mentioned before [0] on your v4 series, I still have the boot hang when CONFIG_DRM_EXYNOS_FIMD is enabled. You said that the cause is u-boot leaving the FIMD DMA engine enabled and so causing IOMMU page faults on init [1].

I tried disabling the display on u-boot but the system hangs remains. But since I do a chain loading using the verified u-boot that comes with the Chromebooks, I don't know if the RO boot-loader is leaving something enabled.

In any case since HDMI with sysmmu is working correctly, that issue is orthogonal to your series and can be fixed as a followup so:

NOTE: Most of the patches don't apply cleanly so I pushed a branch [2] with my conflict resolution so you don't have to do the same. I also did some small changes like using bool instead of int when were assigning it to true and renaming some of the subject lines to match the format used by the subsystem.

What I didn't change is to re-order the sysmmu device nodes according to the unit address that was asked by Andreas since the DTS patches are likely to conflict with the work Krzysztof is doing to use labels instead of overriding nodes in Exynos 4 and 5 DTS[i]. So you may need to change those anyways once Krzysztof patches land.

Best regards,
Javier

[0]: http://lists.infradead.org/pipermail/linux-arm-kernel/2015-January/317727.html
[1]: http://lists.infradead.org/pipermail/linux-arm-kernel/2015-January/319178.html
[2]: http://cgit.collabora.com/git/user/javier/linux.git/log/?h=next20150415-exynos-iommu

author maintainer
#32 lore raw

v5 cover Exynos SYSMMU (IOMMU) integration with DT and DMA-mapping subsystem

Hello,

Quoted 36 lines · Javier Martinez Canillas

Hello Marek,

Quoted 8 lines · Joerg Roedel

Hi Marek,

Quoted 5 lines · Marek Szyprowski

1. All iommu related patches (with 'iommu: exynos') can be merged to iommu tree. They don't have any direct dependencies on the DTS, DRM and power domain initialization change - without them the driver will simply not initialize, when no exynos,sysmmu nodes are provided in device tree.

Quoted 5 lines
Quoted 1 line

Joerg, could you merge those patches?

Given the previous comments and tests on this patch set I am still waiting for some Acked-bys and/or Tested-bys on this. Can you collect these and resend then (probably after the v3.20 merge window)?

I rebased your patches on top of latest linux-next (next-20150415) and tested it on my Exynos5420 Peach Pit. HDMI display is working correctly (both console and X) when CONFIG_DRM_EXYNOS_IOMMU is enabled. I also see that the mixer is attached to the IOMMU domain:

exynos-mixer 14450000.mixer: exynos_iommu_attach_device: Attached IOMMU with pgtable 0x6e5e0000
...
exynos-sysmmu 14650000.sysmmu: Enabled

As I mentioned before [0] on your v4 series, I still have the boot hang when CONFIG_DRM_EXYNOS_FIMD is enabled. You said that the cause is u-boot leaving the FIMD DMA engine enabled and so causing IOMMU page faults on init [1].

I tried disabling the display on u-boot but the system hangs remains. But since I do a chain loading using the verified u-boot that comes with the Chromebooks, I don't know if the RO boot-loader is leaving something enabled.

Quoted 4 lines

In any case since HDMI with sysmmu is working correctly, that issue is orthogonal to your series and can be fixed as a followup so:

In meantime I've managed to add UART adapter to our Chromebook Snow and finally found the issue with FIMD. It was really nasty to debug, because it causes a crash with console lock taken in register_framebuffer(), so there was no debug/crash message - only complete system freeze. All this was caused by fimd left enabled by bootloader, but with gate clock disabled, so any access to its register caused freeze.

I need to cleanup the patches. I will rebase them and send once 4.1rc1 is out. I'm sorry that I didn't let you know earlier, but I'm terribly busy with other (internal) stuff right now.

Quoted 11 lines

NOTE: Most of the patches don't apply cleanly so I pushed a branch [2] with my conflict resolution so you don't have to do the same. I also did some small changes like using bool instead of int when were assigning it to true and renaming some of the subject lines to match the format used by the subsystem.

What I didn't change is to re-order the sysmmu device nodes according to the unit address that was asked by Andreas since the DTS patches are likely to conflict with the work Krzysztof is doing to use labels instead of overriding nodes in Exynos 4 and 5 DTS[i]. So you may need to change those anyways once Krzysztof patches land.

Thanks!

Best regards

Signature · 2 lines
Marek Szyprowski, PhD
Samsung R&D Institute Poland
#33 lore raw

v5 cover Exynos SYSMMU (IOMMU) integration with DT and DMA-mapping subsystem

Hello Marek,

Quoted 47 lines · Marek Szyprowski

Hello,

Quoted 43 lines · Javier Martinez Canillas

Hello Marek,

Quoted 10 lines · Joerg Roedel

Hi Marek,

Quoted 6 lines · Marek Szyprowski

1. All iommu related patches (with 'iommu: exynos') can be merged to iommu tree. They don't have any direct dependencies on the DTS, DRM and power domain initialization change - without them the driver will simply not initialize, when no exynos,sysmmu nodes are provided in device tree.

Quoted 6 lines
Quoted 1 line

Joerg, could you merge those patches?

Given the previous comments and tests on this patch set I am still waiting for some Acked-bys and/or Tested-bys on this. Can you collect these and resend then (probably after the v3.20 merge window)?

I rebased your patches on top of latest linux-next (next-20150415) and tested it on my Exynos5420 Peach Pit. HDMI display is working correctly (both console and X) when CONFIG_DRM_EXYNOS_IOMMU is enabled. I also see that the mixer is attached to the IOMMU domain:

exynos-mixer 14450000.mixer: exynos_iommu_attach_device: Attached IOMMU with pgtable 0x6e5e0000
...
exynos-sysmmu 14650000.sysmmu: Enabled

As I mentioned before [0] on your v4 series, I still have the boot hang when CONFIG_DRM_EXYNOS_FIMD is enabled. You said that the cause is u-boot leaving the FIMD DMA engine enabled and so causing IOMMU page faults on init [1].

I tried disabling the display on u-boot but the system hangs remains. But since I do a chain loading using the verified u-boot that comes with the Chromebooks, I don't know if the RO boot-loader is leaving something enabled.

In any case since HDMI with sysmmu is working correctly, that issue is orthogonal to your series and can be fixed as a followup so:

Quoted 7 lines
Quoted 1 line

In meantime I've managed to add UART adapter to our Chromebook Snow and finally found the issue with FIMD. It was really nasty to debug, because it causes a crash with console lock taken in register_framebuffer(), so there was no debug/crash message - only complete system freeze. All this

Yeah, that's why I was not able to find the cause yet. No output message and just a complete system hang.

Quoted 3 lines

was caused by fimd left enabled by bootloader, but with gate clock disabled, so any access to its register caused freeze.

Awesome, I'm glad that you figured it out.

Interface clocks being gated that are needed to access registers has bitten us too many times, didn't it? :-)

Quoted 4 lines

I need to cleanup the patches. I will rebase them and send once 4.1rc1 is out. I'm sorry that I didn't let you know earlier, but I'm terribly busy with other (internal) stuff right now.

No worries, I was also busy with other stuff and just took a look at this issue again today. I hope my branch could save you some effort for the rebase then.

Quoted 13 lines
Quoted 11 lines

NOTE: Most of the patches don't apply cleanly so I pushed a branch [2] with my conflict resolution so you don't have to do the same. I also did some small changes like using bool instead of int when were assigning it to true and renaming some of the subject lines to match the format used by the subsystem.

What I didn't change is to re-order the sysmmu device nodes according to the unit address that was asked by Andreas since the DTS patches are likely to conflict with the work Krzysztof is doing to use labels instead of overriding nodes in Exynos 4 and 5 DTS[i]. So you may need to change those anyways once Krzysztof patches land.

Quoted 8 lines

Thanks!

Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland

Best regards,
Javier