[tip: timers/core] dt-bindings: timer: renesas, cmt: Add CMT0234 to sh73a0 and r8a7740

2019-08-26 Thread tip-bot2 for Magnus Damm
The following commit has been merged into the timers/core branch of tip:

Commit-ID: c90d37c9c41a572ea7183299951341b4640d5b4b
Gitweb:
https://git.kernel.org/tip/c90d37c9c41a572ea7183299951341b4640d5b4b
Author:Magnus Damm 
AuthorDate:Tue, 20 Aug 2019 21:35:03 +09:00
Committer: Daniel Lezcano 
CommitterDate: Tue, 27 Aug 2019 00:31:39 +02:00

dt-bindings: timer: renesas, cmt: Add CMT0234 to sh73a0 and r8a7740

Document the on-chip CMT devices included in r8a7740 and sh73a0.

Included in this patch is DT binding documentation for 32-bit CMTs
CMT0, CMT2, CMT3 and CMT4. They all contain a single channel and are
quite similar however some minor differences still exist:
 - "Counter input clock" (clock input and on-device divider)
One example is that RCLK 1/1 is supported by CMT2, CMT3 and CMT4.
 - "Wakeup request" (supported by CMT0 and CMT2)

Because of this one unique compat string per CMT device is selected.

Signed-off-by: Magnus Damm 
Reviewed-by: Rob Herring 
Reviewed-by: Simon Horman 
Reviewed-by: Geert Uytterhoeven 
Signed-off-by: Daniel Lezcano 
---
 Documentation/devicetree/bindings/timer/renesas,cmt.txt | 8 
 1 file changed, 8 insertions(+)

diff --git a/Documentation/devicetree/bindings/timer/renesas,cmt.txt 
b/Documentation/devicetree/bindings/timer/renesas,cmt.txt
index c5220bc..45840d4 100644
--- a/Documentation/devicetree/bindings/timer/renesas,cmt.txt
+++ b/Documentation/devicetree/bindings/timer/renesas,cmt.txt
@@ -22,6 +22,10 @@ Required Properties:
 
 - "renesas,r8a73a4-cmt0" for the 32-bit CMT0 device included in r8a73a4.
 - "renesas,r8a73a4-cmt1" for the 48-bit CMT1 device included in r8a73a4.
+- "renesas,r8a7740-cmt0" for the 32-bit CMT0 device included in r8a7740.
+- "renesas,r8a7740-cmt2" for the 32-bit CMT2 device included in r8a7740.
+- "renesas,r8a7740-cmt3" for the 32-bit CMT3 device included in r8a7740.
+- "renesas,r8a7740-cmt4" for the 32-bit CMT4 device included in r8a7740.
 - "renesas,r8a7743-cmt0" for the 32-bit CMT0 device included in r8a7743.
 - "renesas,r8a7743-cmt1" for the 48-bit CMT1 device included in r8a7743.
 - "renesas,r8a7744-cmt0" for the 32-bit CMT0 device included in r8a7744.
@@ -54,6 +58,10 @@ Required Properties:
 - "renesas,r8a77980-cmt1" for the 48-bit CMT1 device included in r8a77980.
 - "renesas,r8a77990-cmt0" for the 32-bit CMT0 device included in r8a77990.
 - "renesas,r8a77990-cmt1" for the 48-bit CMT1 device included in r8a77990.
+- "renesas,sh73a0-cmt0" for the 32-bit CMT0 device included in sh73a0.
+- "renesas,sh73a0-cmt2" for the 32-bit CMT2 device included in sh73a0.
+- "renesas,sh73a0-cmt3" for the 32-bit CMT3 device included in sh73a0.
+- "renesas,sh73a0-cmt4" for the 32-bit CMT4 device included in sh73a0.
 
 - "renesas,rcar-gen2-cmt0" for 32-bit CMT0 devices included in R-Car Gen2
and RZ/G1.


[tip: timers/core] dt-bindings: timer: renesas, cmt: Update R-Car Gen3 CMT1 usage

2019-08-26 Thread tip-bot2 for Magnus Damm
The following commit has been merged into the timers/core branch of tip:

Commit-ID: 1be8c9fd2ac9ad730cf537b8909f66c357866c5d
Gitweb:
https://git.kernel.org/tip/1be8c9fd2ac9ad730cf537b8909f66c357866c5d
Author:Magnus Damm 
AuthorDate:Tue, 20 Aug 2019 21:35:46 +09:00
Committer: Daniel Lezcano 
CommitterDate: Tue, 27 Aug 2019 00:31:39 +02:00

dt-bindings: timer: renesas, cmt: Update R-Car Gen3 CMT1 usage

The R-Car Gen3 SoCs so far come with a total for 4 on-chip CMT devices:
 - CMT0
 - CMT1
 - CMT2
 - CMT3

CMT0 includes two rather basic 32-bit timer channels. The rest of the on-chip
CMT devices support 48-bit counters and have 8 channels each.

Based on the data sheet information "CMT2/3 are exactly same as CMT1"
it seems that CMT2 and CMT3 now use the CMT1 compat string in the DTSI.

Clarify this in the DT binding documentation by describing R-Car Gen3 and
RZ/G2 CMT1 as "48-bit CMT devices".

Signed-off-by: Magnus Damm 
Reviewed-by: Geert Uytterhoeven 
Reviewed-by: Rob Herring 
Reviewed-by: Simon Horman 
Signed-off-by: Daniel Lezcano 
---
 Documentation/devicetree/bindings/timer/renesas,cmt.txt | 20 
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/Documentation/devicetree/bindings/timer/renesas,cmt.txt 
b/Documentation/devicetree/bindings/timer/renesas,cmt.txt
index c7fdcb0..a444cfc 100644
--- a/Documentation/devicetree/bindings/timer/renesas,cmt.txt
+++ b/Documentation/devicetree/bindings/timer/renesas,cmt.txt
@@ -28,9 +28,9 @@ Required Properties:
 - "renesas,r8a77470-cmt0" for the 32-bit CMT0 device included in r8a77470.
 - "renesas,r8a77470-cmt1" for the 48-bit CMT1 device included in r8a77470.
 - "renesas,r8a774a1-cmt0" for the 32-bit CMT0 device included in r8a774a1.
-- "renesas,r8a774a1-cmt1" for the 48-bit CMT1 device included in r8a774a1.
+- "renesas,r8a774a1-cmt1" for the 48-bit CMT devices included in r8a774a1.
 - "renesas,r8a774c0-cmt0" for the 32-bit CMT0 device included in r8a774c0.
-- "renesas,r8a774c0-cmt1" for the 48-bit CMT1 device included in r8a774c0.
+- "renesas,r8a774c0-cmt1" for the 48-bit CMT devices included in r8a774c0.
 - "renesas,r8a7790-cmt0" for the 32-bit CMT0 device included in r8a7790.
 - "renesas,r8a7790-cmt1" for the 48-bit CMT1 device included in r8a7790.
 - "renesas,r8a7791-cmt0" for the 32-bit CMT0 device included in r8a7791.
@@ -42,19 +42,19 @@ Required Properties:
 - "renesas,r8a7794-cmt0" for the 32-bit CMT0 device included in r8a7794.
 - "renesas,r8a7794-cmt1" for the 48-bit CMT1 device included in r8a7794.
 - "renesas,r8a7795-cmt0" for the 32-bit CMT0 device included in r8a7795.
-- "renesas,r8a7795-cmt1" for the 48-bit CMT1 device included in r8a7795.
+- "renesas,r8a7795-cmt1" for the 48-bit CMT devices included in r8a7795.
 - "renesas,r8a7796-cmt0" for the 32-bit CMT0 device included in r8a7796.
-- "renesas,r8a7796-cmt1" for the 48-bit CMT1 device included in r8a7796.
+- "renesas,r8a7796-cmt1" for the 48-bit CMT devices included in r8a7796.
 - "renesas,r8a77965-cmt0" for the 32-bit CMT0 device included in r8a77965.
-- "renesas,r8a77965-cmt1" for the 48-bit CMT1 device included in r8a77965.
+- "renesas,r8a77965-cmt1" for the 48-bit CMT devices included in r8a77965.
 - "renesas,r8a77970-cmt0" for the 32-bit CMT0 device included in r8a77970.
-- "renesas,r8a77970-cmt1" for the 48-bit CMT1 device included in r8a77970.
+- "renesas,r8a77970-cmt1" for the 48-bit CMT devices included in r8a77970.
 - "renesas,r8a77980-cmt0" for the 32-bit CMT0 device included in r8a77980.
-- "renesas,r8a77980-cmt1" for the 48-bit CMT1 device included in r8a77980.
+- "renesas,r8a77980-cmt1" for the 48-bit CMT devices included in r8a77980.
 - "renesas,r8a77990-cmt0" for the 32-bit CMT0 device included in r8a77990.
-- "renesas,r8a77990-cmt1" for the 48-bit CMT1 device included in r8a77990.
+- "renesas,r8a77990-cmt1" for the 48-bit CMT devices included in r8a77990.
 - "renesas,r8a77995-cmt0" for the 32-bit CMT0 device included in r8a77995.
-- "renesas,r8a77995-cmt1" for the 48-bit CMT1 device included in r8a77995.
+- "renesas,r8a77995-cmt1" for the 48-bit CMT devices included in r8a77995.
 - "renesas,sh73a0-cmt0" for the 32-bit CMT0 device included in sh73a0.
 - "renesas,sh73a0-cmt1" for the 48-bit CMT1 device included in sh73a0.
 - "renesas,sh73a0-cmt2" for the 32-bit CMT2 device included in sh73a0.
@@ -69,7 +69,7 @@ Required Properties:
listed above.
 - "renesas,rcar-gen3-cmt0" for 32-bit CMT0 devices included in R-Car Gen3
and RZ/G2.
-- "renesas,rcar-gen3-cmt1" for 48-bit CMT1 devices included in R-Car Gen3
+- "renesas,rcar-gen3-cmt1" for 48-bit CMT devices included in R-Car Gen3
and RZ/G2.
These are fallbacks for R-Car Gen3 and RZ/G2 entries listed
above.


[tip: timers/core] dt-bindings: timer: renesas, cmt: Add CMT0 and CMT1 to r8a7792

2019-08-26 Thread tip-bot2 for Magnus Damm
The following commit has been merged into the timers/core branch of tip:

Commit-ID: 649dd060334f13792f624ec3fa8a0024ed1e02bc
Gitweb:
https://git.kernel.org/tip/649dd060334f13792f624ec3fa8a0024ed1e02bc
Author:Magnus Damm 
AuthorDate:Tue, 20 Aug 2019 21:35:25 +09:00
Committer: Daniel Lezcano 
CommitterDate: Tue, 27 Aug 2019 00:31:39 +02:00

dt-bindings: timer: renesas, cmt: Add CMT0 and CMT1 to r8a7792

This patch adds DT binding documentation for the CMT devices on
the R-Car Gen2 V2H (r8a7792) SoC.

Signed-off-by: Magnus Damm 
Reviewed-by: Geert Uytterhoeven 
Reviewed-by: Rob Herring 
Reviewed-by: Simon Horman 
Signed-off-by: Daniel Lezcano 
---
 Documentation/devicetree/bindings/timer/renesas,cmt.txt | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/timer/renesas,cmt.txt 
b/Documentation/devicetree/bindings/timer/renesas,cmt.txt
index a297fca..5b7690a 100644
--- a/Documentation/devicetree/bindings/timer/renesas,cmt.txt
+++ b/Documentation/devicetree/bindings/timer/renesas,cmt.txt
@@ -35,6 +35,8 @@ Required Properties:
 - "renesas,r8a7790-cmt1" for the 48-bit CMT1 device included in r8a7790.
 - "renesas,r8a7791-cmt0" for the 32-bit CMT0 device included in r8a7791.
 - "renesas,r8a7791-cmt1" for the 48-bit CMT1 device included in r8a7791.
+- "renesas,r8a7792-cmt0" for the 32-bit CMT0 device included in r8a7792.
+- "renesas,r8a7792-cmt1" for the 48-bit CMT1 device included in r8a7792.
 - "renesas,r8a7793-cmt0" for the 32-bit CMT0 device included in r8a7793.
 - "renesas,r8a7793-cmt1" for the 48-bit CMT1 device included in r8a7793.
 - "renesas,r8a7794-cmt0" for the 32-bit CMT0 device included in r8a7794.


[tip: timers/core] dt-bindings: timer: renesas, cmt: Add CMT0 and CMT1 to r8a77995

2019-08-26 Thread tip-bot2 for Magnus Damm
The following commit has been merged into the timers/core branch of tip:

Commit-ID: 53933bc3a69e0f07a1af2fea16fda9c816ffcf87
Gitweb:
https://git.kernel.org/tip/53933bc3a69e0f07a1af2fea16fda9c816ffcf87
Author:Magnus Damm 
AuthorDate:Tue, 20 Aug 2019 21:35:36 +09:00
Committer: Daniel Lezcano 
CommitterDate: Tue, 27 Aug 2019 00:31:39 +02:00

dt-bindings: timer: renesas, cmt: Add CMT0 and CMT1 to r8a77995

This patch adds DT binding documentation for the CMT devices on
the R-Car Gen3 D3 (r8a77995) SoC.

Signed-off-by: Magnus Damm 
Reviewed-by: Geert Uytterhoeven 
Reviewed-by: Rob Herring 
Reviewed-by: Simon Horman 
Signed-off-by: Daniel Lezcano 
---
 Documentation/devicetree/bindings/timer/renesas,cmt.txt | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/timer/renesas,cmt.txt 
b/Documentation/devicetree/bindings/timer/renesas,cmt.txt
index 5b7690a..c7fdcb0 100644
--- a/Documentation/devicetree/bindings/timer/renesas,cmt.txt
+++ b/Documentation/devicetree/bindings/timer/renesas,cmt.txt
@@ -53,6 +53,8 @@ Required Properties:
 - "renesas,r8a77980-cmt1" for the 48-bit CMT1 device included in r8a77980.
 - "renesas,r8a77990-cmt0" for the 32-bit CMT0 device included in r8a77990.
 - "renesas,r8a77990-cmt1" for the 48-bit CMT1 device included in r8a77990.
+- "renesas,r8a77995-cmt0" for the 32-bit CMT0 device included in r8a77995.
+- "renesas,r8a77995-cmt1" for the 48-bit CMT1 device included in r8a77995.
 - "renesas,sh73a0-cmt0" for the 32-bit CMT0 device included in sh73a0.
 - "renesas,sh73a0-cmt1" for the 48-bit CMT1 device included in sh73a0.
 - "renesas,sh73a0-cmt2" for the 32-bit CMT2 device included in sh73a0.


[tip: timers/core] clocksource/drivers/sh_cmt: Document "cmt-48" as deprecated

2019-08-26 Thread tip-bot2 for Magnus Damm
The following commit has been merged into the timers/core branch of tip:

Commit-ID: 19d608458f4f3bb3a1f89bd7e4814c3fd30dbec7
Gitweb:
https://git.kernel.org/tip/19d608458f4f3bb3a1f89bd7e4814c3fd30dbec7
Author:Magnus Damm 
AuthorDate:Tue, 20 Aug 2019 21:36:07 +09:00
Committer: Daniel Lezcano 
CommitterDate: Tue, 27 Aug 2019 00:31:39 +02:00

clocksource/drivers/sh_cmt: Document "cmt-48" as deprecated

Update the CMT driver to mark "renesas,cmt-48" as deprecated.

Instead of documenting a theoretical hardware device based on current software
support level, define DT bindings top-down based on available data sheet
information and make use of part numbers in the DT compat string.

In case of the only in-tree users r8a7740 and sh73a0 the compat strings
"renesas,r8a7740-cmt1" and "renesas,sh73a0-cmt1" may be used instead.

Signed-off-by: Magnus Damm 
Reviewed-by: Simon Horman 
Reviewed-by: Geert Uytterhoeven 
Signed-off-by: Daniel Lezcano 
---
 drivers/clocksource/sh_cmt.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index abf5e78..ef773db 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -918,7 +918,11 @@ static const struct platform_device_id sh_cmt_id_table[] = 
{
 MODULE_DEVICE_TABLE(platform, sh_cmt_id_table);
 
 static const struct of_device_id sh_cmt_of_table[] __maybe_unused = {
-   { .compatible = "renesas,cmt-48", .data = &sh_cmt_info[SH_CMT_48BIT] },
+   {
+   /* deprecated, preserved for backward compatibility */
+   .compatible = "renesas,cmt-48",
+   .data = &sh_cmt_info[SH_CMT_48BIT]
+   },
{
/* deprecated, preserved for backward compatibility */
.compatible = "renesas,cmt-48-gen2",


[tip: timers/core] clocksource/drivers/sh_cmt: r8a7740 and sh73a0 SoC-specific match

2019-08-26 Thread tip-bot2 for Magnus Damm
The following commit has been merged into the timers/core branch of tip:

Commit-ID: 8c1afba285a86b9dbb0637f8c70a34fe2d88569e
Gitweb:
https://git.kernel.org/tip/8c1afba285a86b9dbb0637f8c70a34fe2d88569e
Author:Magnus Damm 
AuthorDate:Tue, 20 Aug 2019 21:35:56 +09:00
Committer: Daniel Lezcano 
CommitterDate: Tue, 27 Aug 2019 00:31:39 +02:00

clocksource/drivers/sh_cmt: r8a7740 and sh73a0 SoC-specific match

Add SoC-specific matching for CMT1 on r8a7740 and sh73a0.

This allows us to move away from the old DT bindings such as
 - "renesas,cmt-48-sh73a0"
 - "renesas,cmt-48-r8a7740"
 - "renesas,cmt-48"
in favour for the now commonly used format "renesas,-"

Signed-off-by: Magnus Damm 
Reviewed-by: Simon Horman 
Reviewed-by: Geert Uytterhoeven 
Signed-off-by: Daniel Lezcano 
---
 drivers/clocksource/sh_cmt.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index f6424b6..abf5e78 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -925,6 +925,14 @@ static const struct of_device_id sh_cmt_of_table[] 
__maybe_unused = {
.data = &sh_cmt_info[SH_CMT0_RCAR_GEN2]
},
{
+   .compatible = "renesas,r8a7740-cmt1",
+   .data = &sh_cmt_info[SH_CMT_48BIT]
+   },
+   {
+   .compatible = "renesas,sh73a0-cmt1",
+   .data = &sh_cmt_info[SH_CMT_48BIT]
+   },
+   {
.compatible = "renesas,rcar-gen2-cmt0",
.data = &sh_cmt_info[SH_CMT0_RCAR_GEN2]
},


[tip: timers/core] dt-bindings: timer: renesas, cmt: Update CMT1 on sh73a0 and r8a7740

2019-08-26 Thread tip-bot2 for Magnus Damm
The following commit has been merged into the timers/core branch of tip:

Commit-ID: 81b604c39997de91f4b2912f803074c85045fe36
Gitweb:
https://git.kernel.org/tip/81b604c39997de91f4b2912f803074c85045fe36
Author:Magnus Damm 
AuthorDate:Tue, 20 Aug 2019 21:35:14 +09:00
Committer: Daniel Lezcano 
CommitterDate: Tue, 27 Aug 2019 00:31:39 +02:00

dt-bindings: timer: renesas, cmt: Update CMT1 on sh73a0 and r8a7740

This patch reworks the DT binding documentation for the 6-channel
48-bit CMTs known as CMT1 on r8a7740 and sh73a0.

After the update the same style of DT binding as the rest of the upstream
SoCs will now also be used by r8a7740 and sh73a0. The DT binding "cmt-48"
is removed from the DT binding documentation, however software support for
this deprecated binding will still remain in the CMT driver for some time.

Signed-off-by: Magnus Damm 
Reviewed-by: Rob Herring 
Reviewed-by: Simon Horman 
Reviewed-by: Geert Uytterhoeven 
Signed-off-by: Daniel Lezcano 
---
 Documentation/devicetree/bindings/timer/renesas,cmt.txt | 10 +---
 1 file changed, 2 insertions(+), 8 deletions(-)

diff --git a/Documentation/devicetree/bindings/timer/renesas,cmt.txt 
b/Documentation/devicetree/bindings/timer/renesas,cmt.txt
index 45840d4..a297fca 100644
--- a/Documentation/devicetree/bindings/timer/renesas,cmt.txt
+++ b/Documentation/devicetree/bindings/timer/renesas,cmt.txt
@@ -12,17 +12,10 @@ datasheets.
 Required Properties:
 
   - compatible: must contain one or more of the following:
-- "renesas,cmt-48-sh73a0" for the sh73A0 48-bit CMT
-   (CMT1)
-- "renesas,cmt-48-r8a7740" for the r8a7740 48-bit CMT
-   (CMT1)
-- "renesas,cmt-48" for all non-second generation 48-bit CMT
-   (CMT1 on sh73a0 and r8a7740)
-   This is a fallback for the above renesas,cmt-48-* entries.
-
 - "renesas,r8a73a4-cmt0" for the 32-bit CMT0 device included in r8a73a4.
 - "renesas,r8a73a4-cmt1" for the 48-bit CMT1 device included in r8a73a4.
 - "renesas,r8a7740-cmt0" for the 32-bit CMT0 device included in r8a7740.
+- "renesas,r8a7740-cmt1" for the 48-bit CMT1 device included in r8a7740.
 - "renesas,r8a7740-cmt2" for the 32-bit CMT2 device included in r8a7740.
 - "renesas,r8a7740-cmt3" for the 32-bit CMT3 device included in r8a7740.
 - "renesas,r8a7740-cmt4" for the 32-bit CMT4 device included in r8a7740.
@@ -59,6 +52,7 @@ Required Properties:
 - "renesas,r8a77990-cmt0" for the 32-bit CMT0 device included in r8a77990.
 - "renesas,r8a77990-cmt1" for the 48-bit CMT1 device included in r8a77990.
 - "renesas,sh73a0-cmt0" for the 32-bit CMT0 device included in sh73a0.
+- "renesas,sh73a0-cmt1" for the 48-bit CMT1 device included in sh73a0.
 - "renesas,sh73a0-cmt2" for the 32-bit CMT2 device included in sh73a0.
 - "renesas,sh73a0-cmt3" for the 32-bit CMT3 device included in sh73a0.
 - "renesas,sh73a0-cmt4" for the 32-bit CMT4 device included in sh73a0.


[PATCH v2 7/7] clocksource/drivers/sh_cmt: Document "cmt-48" as deprecated

2019-08-20 Thread Magnus Damm
From: Magnus Damm 

Update the CMT driver to mark "renesas,cmt-48" as deprecated.

Instead of documenting a theoretical hardware device based on current software
support level, define DT bindings top-down based on available data sheet
information and make use of part numbers in the DT compat string.

In case of the only in-tree users r8a7740 and sh73a0 the compat strings
"renesas,r8a7740-cmt1" and "renesas,sh73a0-cmt1" may be used instead.

Signed-off-by: Magnus Damm 
Reviewed-by: Simon Horman 
---

 drivers/clocksource/sh_cmt.c |6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

--- 0011/drivers/clocksource/sh_cmt.c
+++ work/drivers/clocksource/sh_cmt.c   2019-07-18 19:31:01.917491800 +0900
@@ -921,7 +921,11 @@ static const struct platform_device_id s
 MODULE_DEVICE_TABLE(platform, sh_cmt_id_table);
 
 static const struct of_device_id sh_cmt_of_table[] __maybe_unused = {
-   { .compatible = "renesas,cmt-48", .data = &sh_cmt_info[SH_CMT_48BIT] },
+   {
+   /* deprecated, preserved for backward compatibility */
+   .compatible = "renesas,cmt-48",
+   .data = &sh_cmt_info[SH_CMT_48BIT]
+   },
{
/* deprecated, preserved for backward compatibility */
.compatible = "renesas,cmt-48-gen2",


[PATCH v2 6/7] clocksource/drivers/sh_cmt: r8a7740 and sh73a0 SoC-specific match

2019-08-20 Thread Magnus Damm
From: Magnus Damm 

Add SoC-specific matching for CMT1 on r8a7740 and sh73a0.

This allows us to move away from the old DT bindings such as
 - "renesas,cmt-48-sh73a0"
 - "renesas,cmt-48-r8a7740"
 - "renesas,cmt-48"
in favour for the now commonly used format "renesas,-"

Signed-off-by: Magnus Damm 
Reviewed-by: Simon Horman 
---

 drivers/clocksource/sh_cmt.c |8 
 1 file changed, 8 insertions(+)

--- 0001/drivers/clocksource/sh_cmt.c
+++ work/drivers/clocksource/sh_cmt.c   2019-07-18 19:29:06.005414716 +0900
@@ -928,6 +928,14 @@ static const struct of_device_id sh_cmt_
.data = &sh_cmt_info[SH_CMT0_RCAR_GEN2]
},
{
+   .compatible = "renesas,r8a7740-cmt1",
+   .data = &sh_cmt_info[SH_CMT_48BIT]
+   },
+   {
+   .compatible = "renesas,sh73a0-cmt1",
+   .data = &sh_cmt_info[SH_CMT_48BIT]
+   },
+   {
.compatible = "renesas,rcar-gen2-cmt0",
.data = &sh_cmt_info[SH_CMT0_RCAR_GEN2]
},


Re: [PATCH 6/7] clocksource/drivers/sh_cmt: r8a7740 and sh73a0 SoC-specific match

2019-08-20 Thread Magnus Damm
Hi Simon,

On Wed, Jul 24, 2019 at 8:12 PM Simon Horman  wrote:
>
> On Thu, Jul 18, 2019 at 08:45:24PM +0900, Magnus Damm wrote:
> > From: Magnus Damm 
> >
> > Add SoC-specific matching for CMT1 on r8a7740 and sh73a0.
> >
> > This allows us to move away from the old DT bindings such as
> >  - "renesas,cmt-48-sh73a0"
> >  - "renesas,cmt-48-r8a7740"
> >  - "renesas,cmt-48"
> > in favour for the now commonly used format "renesas,-"
> >
> > Signed-off-by: Magnus Damm 
>
> Reviewed-by: Simon Horman 

Thanks!

> > ---
> >
> >  drivers/clocksource/sh_cmt.c |8 
> >  1 file changed, 8 insertions(+)
> >
> > --- 0001/drivers/clocksource/sh_cmt.c
> > +++ work/drivers/clocksource/sh_cmt.c 2019-07-18 19:29:06.005414716 +0900
> > @@ -928,6 +928,14 @@ static const struct of_device_id sh_cmt_
> >   .data = &sh_cmt_info[SH_CMT0_RCAR_GEN2]
> >   },
> >   {
> > + .compatible = "renesas,r8a7740-cmt1",
> > + .data = &sh_cmt_info[SH_CMT_48BIT]
>
> Perhaps as a follow-up SH_CMT_48BIT could be renamed.

I was actually considering implementing proper 48-bit support, and
reworking those names might be a good idea at that point.

Cheers,

/ magnus


[PATCH v2 2/7] dt-bindings: timer: renesas, cmt: Update CMT1 on sh73a0 and r8a7740

2019-08-20 Thread Magnus Damm
From: Magnus Damm 

This patch reworks the DT binding documentation for the 6-channel
48-bit CMTs known as CMT1 on r8a7740 and sh73a0.

After the update the same style of DT binding as the rest of the upstream
SoCs will now also be used by r8a7740 and sh73a0. The DT binding "cmt-48"
is removed from the DT binding documentation, however software support for
this deprecated binding will still remain in the CMT driver for some time.

Signed-off-by: Magnus Damm 
Reviewed-by: Rob Herring 
Reviewed-by: Simon Horman 
---

 Documentation/devicetree/bindings/timer/renesas,cmt.txt |   10 ++
 1 file changed, 2 insertions(+), 8 deletions(-)

--- 0002/Documentation/devicetree/bindings/timer/renesas,cmt.txt
+++ work/Documentation/devicetree/bindings/timer/renesas,cmt.txt
2019-07-18 18:21:59.453309074 +0900
@@ -12,17 +12,10 @@ datasheets.
 Required Properties:
 
   - compatible: must contain one or more of the following:
-- "renesas,cmt-48-sh73a0" for the sh73A0 48-bit CMT
-   (CMT1)
-- "renesas,cmt-48-r8a7740" for the r8a7740 48-bit CMT
-   (CMT1)
-- "renesas,cmt-48" for all non-second generation 48-bit CMT
-   (CMT1 on sh73a0 and r8a7740)
-   This is a fallback for the above renesas,cmt-48-* entries.
-
 - "renesas,r8a73a4-cmt0" for the 32-bit CMT0 device included in r8a73a4.
 - "renesas,r8a73a4-cmt1" for the 48-bit CMT1 device included in r8a73a4.
 - "renesas,r8a7740-cmt0" for the 32-bit CMT0 device included in r8a7740.
+- "renesas,r8a7740-cmt1" for the 48-bit CMT1 device included in r8a7740.
 - "renesas,r8a7740-cmt2" for the 32-bit CMT2 device included in r8a7740.
 - "renesas,r8a7740-cmt3" for the 32-bit CMT3 device included in r8a7740.
 - "renesas,r8a7740-cmt4" for the 32-bit CMT4 device included in r8a7740.
@@ -59,6 +52,7 @@ Required Properties:
 - "renesas,r8a77990-cmt0" for the 32-bit CMT0 device included in r8a77990.
 - "renesas,r8a77990-cmt1" for the 48-bit CMT1 device included in r8a77990.
 - "renesas,sh73a0-cmt0" for the 32-bit CMT0 device included in sh73a0.
+- "renesas,sh73a0-cmt1" for the 48-bit CMT1 device included in sh73a0.
 - "renesas,sh73a0-cmt2" for the 32-bit CMT2 device included in sh73a0.
 - "renesas,sh73a0-cmt3" for the 32-bit CMT3 device included in sh73a0.
 - "renesas,sh73a0-cmt4" for the 32-bit CMT4 device included in sh73a0.


[PATCH v2 5/7] dt-bindings: timer: renesas, cmt: Update R-Car Gen3 CMT1 usage

2019-08-20 Thread Magnus Damm
From: Magnus Damm 

The R-Car Gen3 SoCs so far come with a total for 4 on-chip CMT devices:
 - CMT0
 - CMT1
 - CMT2
 - CMT3

CMT0 includes two rather basic 32-bit timer channels. The rest of the on-chip
CMT devices support 48-bit counters and have 8 channels each.

Based on the data sheet information "CMT2/3 are exactly same as CMT1"
it seems that CMT2 and CMT3 now use the CMT1 compat string in the DTSI.

Clarify this in the DT binding documentation by describing R-Car Gen3 and
RZ/G2 CMT1 as "48-bit CMT devices".

Signed-off-by: Magnus Damm 
Reviewed-by: Geert Uytterhoeven 
Reviewed-by: Rob Herring 
Reviewed-by: Simon Horman 
---

 Changes since last version:
 - Use "devices" for fallback entry - thanks Geert!
 - Keen to Gen3 so removed out-of-scope Gen2 portions

 Documentation/devicetree/bindings/timer/renesas,cmt.txt |   20 +++
 1 file changed, 10 insertions(+), 10 deletions(-)

--- 0008/Documentation/devicetree/bindings/timer/renesas,cmt.txt
+++ work/Documentation/devicetree/bindings/timer/renesas,cmt.txt
2019-07-18 19:24:05.195643742 +0900
@@ -28,9 +28,9 @@ Required Properties:
 - "renesas,r8a77470-cmt0" for the 32-bit CMT0 device included in r8a77470.
 - "renesas,r8a77470-cmt1" for the 48-bit CMT1 device included in r8a77470.
 - "renesas,r8a774a1-cmt0" for the 32-bit CMT0 device included in r8a774a1.
-- "renesas,r8a774a1-cmt1" for the 48-bit CMT1 device included in r8a774a1.
+- "renesas,r8a774a1-cmt1" for the 48-bit CMT devices included in r8a774a1.
 - "renesas,r8a774c0-cmt0" for the 32-bit CMT0 device included in r8a774c0.
-- "renesas,r8a774c0-cmt1" for the 48-bit CMT1 device included in r8a774c0.
+- "renesas,r8a774c0-cmt1" for the 48-bit CMT devices included in r8a774c0.
 - "renesas,r8a7790-cmt0" for the 32-bit CMT0 device included in r8a7790.
 - "renesas,r8a7790-cmt1" for the 48-bit CMT1 device included in r8a7790.
 - "renesas,r8a7791-cmt0" for the 32-bit CMT0 device included in r8a7791.
@@ -42,19 +42,19 @@ Required Properties:
 - "renesas,r8a7794-cmt0" for the 32-bit CMT0 device included in r8a7794.
 - "renesas,r8a7794-cmt1" for the 48-bit CMT1 device included in r8a7794.
 - "renesas,r8a7795-cmt0" for the 32-bit CMT0 device included in r8a7795.
-- "renesas,r8a7795-cmt1" for the 48-bit CMT1 device included in r8a7795.
+- "renesas,r8a7795-cmt1" for the 48-bit CMT devices included in r8a7795.
 - "renesas,r8a7796-cmt0" for the 32-bit CMT0 device included in r8a7796.
-- "renesas,r8a7796-cmt1" for the 48-bit CMT1 device included in r8a7796.
+- "renesas,r8a7796-cmt1" for the 48-bit CMT devices included in r8a7796.
 - "renesas,r8a77965-cmt0" for the 32-bit CMT0 device included in r8a77965.
-- "renesas,r8a77965-cmt1" for the 48-bit CMT1 device included in r8a77965.
+- "renesas,r8a77965-cmt1" for the 48-bit CMT devices included in r8a77965.
 - "renesas,r8a77970-cmt0" for the 32-bit CMT0 device included in r8a77970.
-- "renesas,r8a77970-cmt1" for the 48-bit CMT1 device included in r8a77970.
+- "renesas,r8a77970-cmt1" for the 48-bit CMT devices included in r8a77970.
 - "renesas,r8a77980-cmt0" for the 32-bit CMT0 device included in r8a77980.
-- "renesas,r8a77980-cmt1" for the 48-bit CMT1 device included in r8a77980.
+- "renesas,r8a77980-cmt1" for the 48-bit CMT devices included in r8a77980.
 - "renesas,r8a77990-cmt0" for the 32-bit CMT0 device included in r8a77990.
-- "renesas,r8a77990-cmt1" for the 48-bit CMT1 device included in r8a77990.
+- "renesas,r8a77990-cmt1" for the 48-bit CMT devices included in r8a77990.
 - "renesas,r8a77995-cmt0" for the 32-bit CMT0 device included in r8a77995.
-- "renesas,r8a77995-cmt1" for the 48-bit CMT1 device included in r8a77995.
+- "renesas,r8a77995-cmt1" for the 48-bit CMT devices included in r8a77995.
 - "renesas,sh73a0-cmt0" for the 32-bit CMT0 device included in sh73a0.
 - "renesas,sh73a0-cmt1" for the 48-bit CMT1 device included in sh73a0.
 - "renesas,sh73a0-cmt2" for the 32-bit CMT2 device included in sh73a0.
@@ -69,7 +69,7 @@ Required Properties:
listed above.
 - "renesas,rcar-gen3-cmt0" for 32-bit CMT0 devices included in R-Car Gen3
and RZ/G2.
-- "renesas,rcar-gen3-cmt1" for 48-bit CMT1 devices included in R-Car Gen3
+- "renesas,rcar-gen3-cmt1" for 48-bit CMT devices included in R-Car Gen3
and RZ/G2.
These are fallbacks for R-Car Gen3 and RZ/G2 entries listed
above.


[PATCH v2 4/7] dt-bindings: timer: renesas, cmt: Add CMT0 and CMT1 to r8a77995

2019-08-20 Thread Magnus Damm
From: Magnus Damm 

This patch adds DT binding documentation for the CMT devices on
the R-Car Gen3 D3 (r8a77995) SoC.

Signed-off-by: Magnus Damm 
Reviewed-by: Geert Uytterhoeven 
Reviewed-by: Rob Herring 
Reviewed-by: Simon Horman 
---

 Documentation/devicetree/bindings/timer/renesas,cmt.txt |2 ++
 1 file changed, 2 insertions(+)

--- 0006/Documentation/devicetree/bindings/timer/renesas,cmt.txt
+++ work/Documentation/devicetree/bindings/timer/renesas,cmt.txt
2019-07-18 18:25:04.331001914 +0900
@@ -53,6 +53,8 @@ Required Properties:
 - "renesas,r8a77980-cmt1" for the 48-bit CMT1 device included in r8a77980.
 - "renesas,r8a77990-cmt0" for the 32-bit CMT0 device included in r8a77990.
 - "renesas,r8a77990-cmt1" for the 48-bit CMT1 device included in r8a77990.
+- "renesas,r8a77995-cmt0" for the 32-bit CMT0 device included in r8a77995.
+- "renesas,r8a77995-cmt1" for the 48-bit CMT1 device included in r8a77995.
 - "renesas,sh73a0-cmt0" for the 32-bit CMT0 device included in sh73a0.
 - "renesas,sh73a0-cmt1" for the 48-bit CMT1 device included in sh73a0.
 - "renesas,sh73a0-cmt2" for the 32-bit CMT2 device included in sh73a0.


[PATCH v2 3/7] dt-bindings: timer: renesas, cmt: Add CMT0 and CMT1 to r8a7792

2019-08-20 Thread Magnus Damm
From: Magnus Damm 

This patch adds DT binding documentation for the CMT devices on
the R-Car Gen2 V2H (r8a7792) SoC.

Signed-off-by: Magnus Damm 
Reviewed-by: Geert Uytterhoeven 
Reviewed-by: Rob Herring 
Reviewed-by: Simon Horman 
---

 Documentation/devicetree/bindings/timer/renesas,cmt.txt |2 ++
 1 file changed, 2 insertions(+)

--- 0004/Documentation/devicetree/bindings/timer/renesas,cmt.txt
+++ work/Documentation/devicetree/bindings/timer/renesas,cmt.txt
2019-07-18 18:23:48.256013425 +0900
@@ -35,6 +35,8 @@ Required Properties:
 - "renesas,r8a7790-cmt1" for the 48-bit CMT1 device included in r8a7790.
 - "renesas,r8a7791-cmt0" for the 32-bit CMT0 device included in r8a7791.
 - "renesas,r8a7791-cmt1" for the 48-bit CMT1 device included in r8a7791.
+- "renesas,r8a7792-cmt0" for the 32-bit CMT0 device included in r8a7792.
+- "renesas,r8a7792-cmt1" for the 48-bit CMT1 device included in r8a7792.
 - "renesas,r8a7793-cmt0" for the 32-bit CMT0 device included in r8a7793.
 - "renesas,r8a7793-cmt1" for the 48-bit CMT1 device included in r8a7793.
 - "renesas,r8a7794-cmt0" for the 32-bit CMT0 device included in r8a7794.


[PATCH v2 1/7] dt-bindings: timer: renesas, cmt: Add CMT0234 to sh73a0 and r8a7740

2019-08-20 Thread Magnus Damm
From: Magnus Damm 

Document the on-chip CMT devices included in r8a7740 and sh73a0.

Included in this patch is DT binding documentation for 32-bit CMTs
CMT0, CMT2, CMT3 and CMT4. They all contain a single channel and are
quite similar however some minor differences still exist:
 - "Counter input clock" (clock input and on-device divider)
One example is that RCLK 1/1 is supported by CMT2, CMT3 and CMT4.
 - "Wakeup request" (supported by CMT0 and CMT2)

Because of this one unique compat string per CMT device is selected.

Signed-off-by: Magnus Damm 
Reviewed-by: Rob Herring 
Reviewed-by: Simon Horman 
---

 Documentation/devicetree/bindings/timer/renesas,cmt.txt |8 
 1 file changed, 8 insertions(+)

--- 0001/Documentation/devicetree/bindings/timer/renesas,cmt.txt
+++ work/Documentation/devicetree/bindings/timer/renesas,cmt.txt
2019-07-18 18:19:43.196165331 +0900
@@ -22,6 +22,10 @@ Required Properties:
 
 - "renesas,r8a73a4-cmt0" for the 32-bit CMT0 device included in r8a73a4.
 - "renesas,r8a73a4-cmt1" for the 48-bit CMT1 device included in r8a73a4.
+- "renesas,r8a7740-cmt0" for the 32-bit CMT0 device included in r8a7740.
+- "renesas,r8a7740-cmt2" for the 32-bit CMT2 device included in r8a7740.
+- "renesas,r8a7740-cmt3" for the 32-bit CMT3 device included in r8a7740.
+- "renesas,r8a7740-cmt4" for the 32-bit CMT4 device included in r8a7740.
 - "renesas,r8a7743-cmt0" for the 32-bit CMT0 device included in r8a7743.
 - "renesas,r8a7743-cmt1" for the 48-bit CMT1 device included in r8a7743.
 - "renesas,r8a7744-cmt0" for the 32-bit CMT0 device included in r8a7744.
@@ -54,6 +58,10 @@ Required Properties:
 - "renesas,r8a77980-cmt1" for the 48-bit CMT1 device included in r8a77980.
 - "renesas,r8a77990-cmt0" for the 32-bit CMT0 device included in r8a77990.
 - "renesas,r8a77990-cmt1" for the 48-bit CMT1 device included in r8a77990.
+- "renesas,sh73a0-cmt0" for the 32-bit CMT0 device included in sh73a0.
+- "renesas,sh73a0-cmt2" for the 32-bit CMT2 device included in sh73a0.
+- "renesas,sh73a0-cmt3" for the 32-bit CMT3 device included in sh73a0.
+- "renesas,sh73a0-cmt4" for the 32-bit CMT4 device included in sh73a0.
 
 - "renesas,rcar-gen2-cmt0" for 32-bit CMT0 devices included in R-Car Gen2
and RZ/G1.


[PATCH v2 0/7] renesas, cmt: DT Binding Documentation and Minor Driver Updates V2

2019-08-20 Thread Magnus Damm
renesas, cmt: DT Binding Documentation and Minor Driver Updates V2

[PATCH v2 1/7] dt-bindings: timer: renesas, cmt: Add CMT0234 to sh73a0 and 
r8a7740
[PATCH v2 2/7] dt-bindings: timer: renesas, cmt: Update CMT1 on sh73a0 and 
r8a7740
[PATCH v2 3/7] dt-bindings: timer: renesas, cmt: Add CMT0 and CMT1 to r8a7792
[PATCH v2 4/7] dt-bindings: timer: renesas, cmt: Add CMT0 and CMT1 to r8a77995
[PATCH v2 5/7] dt-bindings: timer: renesas, cmt: Update R-Car Gen3 CMT1 usage
[PATCH v2 6/7] clocksource/drivers/sh_cmt: r8a7740 and sh73a0 SoC-specific match
[PATCH v2 7/7] clocksource/drivers/sh_cmt: Document "cmt-48" as deprecated 

This series collect the following rather trivial changes for the CMT driver:
- Add 32-bit CMT0234 and convert CMT1 DT binding docs on sh73a0 and r8a7740.
- Add documentation for the CMT on the R-Car Gen2 V2H (r8a7792) SoC.
- Add missing R-Car Gen3 DT binding documentation for D3 (r8a77995).
- Update the R-Car Gen3 DT documentation to reflect current usage.
- Introduce SoC-specific matching in the driver for CMT1 on sh73a0 and sh73a0.
- Document old "cmt-48" binding as deprecated in the driver.

Since V1 the only update is the addition of reviewed-by from Simon - thanks!

Please see each individual patch for more detailed information.

Signed-off-by: Magnus Damm 
Reviewed-by: Geert Uytterhoeven  [Patch 3-5]
Reviewed-by: Rob Herring  [Patch 1-5]
Reviewed-by: Simon Horman 
---

Developed on top of "renesas-drivers-2019-08-13-v5.3-rc4". Earlier posted as:
[PATCH 0/7] renesas, cmt: DT Binding Documentation and Minor Driver Updates

 Documentation/devicetree/bindings/timer/renesas,cmt.txt |   42 ---
 drivers/clocksource/sh_cmt.c|   14 -
 2 files changed, 37 insertions(+), 19 deletions(-)




[PATCH 6/7] clocksource/drivers/sh_cmt: r8a7740 and sh73a0 SoC-specific match

2019-07-18 Thread Magnus Damm
From: Magnus Damm 

Add SoC-specific matching for CMT1 on r8a7740 and sh73a0.

This allows us to move away from the old DT bindings such as
 - "renesas,cmt-48-sh73a0"
 - "renesas,cmt-48-r8a7740"
 - "renesas,cmt-48"
in favour for the now commonly used format "renesas,-"

Signed-off-by: Magnus Damm 
---

 drivers/clocksource/sh_cmt.c |8 
 1 file changed, 8 insertions(+)

--- 0001/drivers/clocksource/sh_cmt.c
+++ work/drivers/clocksource/sh_cmt.c   2019-07-18 19:29:06.005414716 +0900
@@ -928,6 +928,14 @@ static const struct of_device_id sh_cmt_
.data = &sh_cmt_info[SH_CMT0_RCAR_GEN2]
},
{
+   .compatible = "renesas,r8a7740-cmt1",
+   .data = &sh_cmt_info[SH_CMT_48BIT]
+   },
+   {
+   .compatible = "renesas,sh73a0-cmt1",
+   .data = &sh_cmt_info[SH_CMT_48BIT]
+   },
+   {
.compatible = "renesas,rcar-gen2-cmt0",
.data = &sh_cmt_info[SH_CMT0_RCAR_GEN2]
},


[PATCH 7/7] clocksource/drivers/sh_cmt: Document "cmt-48" as deprecated

2019-07-18 Thread Magnus Damm
From: Magnus Damm 

Update the CMT driver to mark "renesas,cmt-48" as deprecated.

Instead of documenting a theoretical hardware device based on current software
support level, define DT bindings top-down based on available data sheet
information and make use of part numbers in the DT compat string.

In case of the only in-tree users r8a7740 and sh73a0 the compat strings
"renesas,r8a7740-cmt1" and "renesas,sh73a0-cmt1" may be used instead.

Signed-off-by: Magnus Damm 
---

 drivers/clocksource/sh_cmt.c |6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

--- 0011/drivers/clocksource/sh_cmt.c
+++ work/drivers/clocksource/sh_cmt.c   2019-07-18 19:31:01.917491800 +0900
@@ -921,7 +921,11 @@ static const struct platform_device_id s
 MODULE_DEVICE_TABLE(platform, sh_cmt_id_table);
 
 static const struct of_device_id sh_cmt_of_table[] __maybe_unused = {
-   { .compatible = "renesas,cmt-48", .data = &sh_cmt_info[SH_CMT_48BIT] },
+   {
+   /* deprecated, preserved for backward compatibility */
+   .compatible = "renesas,cmt-48",
+   .data = &sh_cmt_info[SH_CMT_48BIT]
+   },
{
/* deprecated, preserved for backward compatibility */
.compatible = "renesas,cmt-48-gen2",


[PATCH 4/7] dt-bindings: timer: renesas, cmt: Add CMT0 and CMT1 to r8a77995

2019-07-18 Thread Magnus Damm
From: Magnus Damm 

This patch adds DT binding documentation for the CMT devices on
the R-Car Gen3 D3 (r8a77995) SoC.

Signed-off-by: Magnus Damm 
Reviewed-by: Geert Uytterhoeven 
Reviewed-by: Rob Herring 
---

 Documentation/devicetree/bindings/timer/renesas,cmt.txt |2 ++
 1 file changed, 2 insertions(+)

--- 0006/Documentation/devicetree/bindings/timer/renesas,cmt.txt
+++ work/Documentation/devicetree/bindings/timer/renesas,cmt.txt
2019-07-18 18:25:04.331001914 +0900
@@ -53,6 +53,8 @@ Required Properties:
 - "renesas,r8a77980-cmt1" for the 48-bit CMT1 device included in r8a77980.
 - "renesas,r8a77990-cmt0" for the 32-bit CMT0 device included in r8a77990.
 - "renesas,r8a77990-cmt1" for the 48-bit CMT1 device included in r8a77990.
+- "renesas,r8a77995-cmt0" for the 32-bit CMT0 device included in r8a77995.
+- "renesas,r8a77995-cmt1" for the 48-bit CMT1 device included in r8a77995.
 - "renesas,sh73a0-cmt0" for the 32-bit CMT0 device included in sh73a0.
 - "renesas,sh73a0-cmt1" for the 48-bit CMT1 device included in sh73a0.
 - "renesas,sh73a0-cmt2" for the 32-bit CMT2 device included in sh73a0.


[PATCH 5/7] dt-bindings: timer: renesas, cmt: Update R-Car Gen3 CMT1 usage

2019-07-18 Thread Magnus Damm
From: Magnus Damm 

The R-Car Gen3 SoCs so far come with a total for 4 on-chip CMT devices:
 - CMT0
 - CMT1
 - CMT2
 - CMT3

CMT0 includes two rather basic 32-bit timer channels. The rest of the on-chip
CMT devices support 48-bit counters and have 8 channels each.

Based on the data sheet information "CMT2/3 are exactly same as CMT1"
it seems that CMT2 and CMT3 now use the CMT1 compat string in the DTSI.

Clarify this in the DT binding documentation by describing R-Car Gen3 and
RZ/G2 CMT1 as "48-bit CMT devices".

Signed-off-by: Magnus Damm 
Reviewed-by: Geert Uytterhoeven 
Reviewed-by: Rob Herring 
---

 Changes since last version:
 - Use "devices" for fallback entry - thanks Geert!
 - Keen to Gen3 so removed out-of-scope Gen2 portions

 Documentation/devicetree/bindings/timer/renesas,cmt.txt |   20 +++
 1 file changed, 10 insertions(+), 10 deletions(-)

--- 0008/Documentation/devicetree/bindings/timer/renesas,cmt.txt
+++ work/Documentation/devicetree/bindings/timer/renesas,cmt.txt
2019-07-18 19:24:05.195643742 +0900
@@ -28,9 +28,9 @@ Required Properties:
 - "renesas,r8a77470-cmt0" for the 32-bit CMT0 device included in r8a77470.
 - "renesas,r8a77470-cmt1" for the 48-bit CMT1 device included in r8a77470.
 - "renesas,r8a774a1-cmt0" for the 32-bit CMT0 device included in r8a774a1.
-- "renesas,r8a774a1-cmt1" for the 48-bit CMT1 device included in r8a774a1.
+- "renesas,r8a774a1-cmt1" for the 48-bit CMT devices included in r8a774a1.
 - "renesas,r8a774c0-cmt0" for the 32-bit CMT0 device included in r8a774c0.
-- "renesas,r8a774c0-cmt1" for the 48-bit CMT1 device included in r8a774c0.
+- "renesas,r8a774c0-cmt1" for the 48-bit CMT devices included in r8a774c0.
 - "renesas,r8a7790-cmt0" for the 32-bit CMT0 device included in r8a7790.
 - "renesas,r8a7790-cmt1" for the 48-bit CMT1 device included in r8a7790.
 - "renesas,r8a7791-cmt0" for the 32-bit CMT0 device included in r8a7791.
@@ -42,19 +42,19 @@ Required Properties:
 - "renesas,r8a7794-cmt0" for the 32-bit CMT0 device included in r8a7794.
 - "renesas,r8a7794-cmt1" for the 48-bit CMT1 device included in r8a7794.
 - "renesas,r8a7795-cmt0" for the 32-bit CMT0 device included in r8a7795.
-- "renesas,r8a7795-cmt1" for the 48-bit CMT1 device included in r8a7795.
+- "renesas,r8a7795-cmt1" for the 48-bit CMT devices included in r8a7795.
 - "renesas,r8a7796-cmt0" for the 32-bit CMT0 device included in r8a7796.
-- "renesas,r8a7796-cmt1" for the 48-bit CMT1 device included in r8a7796.
+- "renesas,r8a7796-cmt1" for the 48-bit CMT devices included in r8a7796.
 - "renesas,r8a77965-cmt0" for the 32-bit CMT0 device included in r8a77965.
-- "renesas,r8a77965-cmt1" for the 48-bit CMT1 device included in r8a77965.
+- "renesas,r8a77965-cmt1" for the 48-bit CMT devices included in r8a77965.
 - "renesas,r8a77970-cmt0" for the 32-bit CMT0 device included in r8a77970.
-- "renesas,r8a77970-cmt1" for the 48-bit CMT1 device included in r8a77970.
+- "renesas,r8a77970-cmt1" for the 48-bit CMT devices included in r8a77970.
 - "renesas,r8a77980-cmt0" for the 32-bit CMT0 device included in r8a77980.
-- "renesas,r8a77980-cmt1" for the 48-bit CMT1 device included in r8a77980.
+- "renesas,r8a77980-cmt1" for the 48-bit CMT devices included in r8a77980.
 - "renesas,r8a77990-cmt0" for the 32-bit CMT0 device included in r8a77990.
-- "renesas,r8a77990-cmt1" for the 48-bit CMT1 device included in r8a77990.
+- "renesas,r8a77990-cmt1" for the 48-bit CMT devices included in r8a77990.
 - "renesas,r8a77995-cmt0" for the 32-bit CMT0 device included in r8a77995.
-- "renesas,r8a77995-cmt1" for the 48-bit CMT1 device included in r8a77995.
+- "renesas,r8a77995-cmt1" for the 48-bit CMT devices included in r8a77995.
 - "renesas,sh73a0-cmt0" for the 32-bit CMT0 device included in sh73a0.
 - "renesas,sh73a0-cmt1" for the 48-bit CMT1 device included in sh73a0.
 - "renesas,sh73a0-cmt2" for the 32-bit CMT2 device included in sh73a0.
@@ -69,7 +69,7 @@ Required Properties:
listed above.
 - "renesas,rcar-gen3-cmt0" for 32-bit CMT0 devices included in R-Car Gen3
and RZ/G2.
-- "renesas,rcar-gen3-cmt1" for 48-bit CMT1 devices included in R-Car Gen3
+- "renesas,rcar-gen3-cmt1" for 48-bit CMT devices included in R-Car Gen3
and RZ/G2.
These are fallbacks for R-Car Gen3 and RZ/G2 entries listed
above.


[PATCH 2/7] dt-bindings: timer: renesas, cmt: Update CMT1 on sh73a0 and r8a7740

2019-07-18 Thread Magnus Damm
From: Magnus Damm 

This patch reworks the DT binding documentation for the 6-channel
48-bit CMTs known as CMT1 on r8a7740 and sh73a0.

After the update the same style of DT binding as the rest of the upstream
SoCs will now also be used by r8a7740 and sh73a0. The DT binding "cmt-48"
is removed from the DT binding documentation, however software support for
this deprecated binding will still remain in the CMT driver for some time.

Signed-off-by: Magnus Damm 
Reviewed-by: Rob Herring 
---

 Documentation/devicetree/bindings/timer/renesas,cmt.txt |   10 ++
 1 file changed, 2 insertions(+), 8 deletions(-)

--- 0002/Documentation/devicetree/bindings/timer/renesas,cmt.txt
+++ work/Documentation/devicetree/bindings/timer/renesas,cmt.txt
2019-07-18 18:21:59.453309074 +0900
@@ -12,17 +12,10 @@ datasheets.
 Required Properties:
 
   - compatible: must contain one or more of the following:
-- "renesas,cmt-48-sh73a0" for the sh73A0 48-bit CMT
-   (CMT1)
-- "renesas,cmt-48-r8a7740" for the r8a7740 48-bit CMT
-   (CMT1)
-- "renesas,cmt-48" for all non-second generation 48-bit CMT
-   (CMT1 on sh73a0 and r8a7740)
-   This is a fallback for the above renesas,cmt-48-* entries.
-
 - "renesas,r8a73a4-cmt0" for the 32-bit CMT0 device included in r8a73a4.
 - "renesas,r8a73a4-cmt1" for the 48-bit CMT1 device included in r8a73a4.
 - "renesas,r8a7740-cmt0" for the 32-bit CMT0 device included in r8a7740.
+- "renesas,r8a7740-cmt1" for the 48-bit CMT1 device included in r8a7740.
 - "renesas,r8a7740-cmt2" for the 32-bit CMT2 device included in r8a7740.
 - "renesas,r8a7740-cmt3" for the 32-bit CMT3 device included in r8a7740.
 - "renesas,r8a7740-cmt4" for the 32-bit CMT4 device included in r8a7740.
@@ -59,6 +52,7 @@ Required Properties:
 - "renesas,r8a77990-cmt0" for the 32-bit CMT0 device included in r8a77990.
 - "renesas,r8a77990-cmt1" for the 48-bit CMT1 device included in r8a77990.
 - "renesas,sh73a0-cmt0" for the 32-bit CMT0 device included in sh73a0.
+- "renesas,sh73a0-cmt1" for the 48-bit CMT1 device included in sh73a0.
 - "renesas,sh73a0-cmt2" for the 32-bit CMT2 device included in sh73a0.
 - "renesas,sh73a0-cmt3" for the 32-bit CMT3 device included in sh73a0.
 - "renesas,sh73a0-cmt4" for the 32-bit CMT4 device included in sh73a0.


[PATCH 1/7] dt-bindings: timer: renesas, cmt: Add CMT0234 to sh73a0 and r8a7740

2019-07-18 Thread Magnus Damm
From: Magnus Damm 

Document the on-chip CMT devices included in r8a7740 and sh73a0.

Included in this patch is DT binding documentation for 32-bit CMTs
CMT0, CMT2, CMT3 and CMT4. They all contain a single channel and are
quite similar however some minor differences still exist:
 - "Counter input clock" (clock input and on-device divider)
One example is that RCLK 1/1 is supported by CMT2, CMT3 and CMT4.
 - "Wakeup request" (supported by CMT0 and CMT2)

Because of this one unique compat string per CMT device is selected.

Signed-off-by: Magnus Damm 
Reviewed-by: Rob Herring 
---

 Documentation/devicetree/bindings/timer/renesas,cmt.txt |8 
 1 file changed, 8 insertions(+)

--- 0001/Documentation/devicetree/bindings/timer/renesas,cmt.txt
+++ work/Documentation/devicetree/bindings/timer/renesas,cmt.txt
2019-07-18 18:19:43.196165331 +0900
@@ -22,6 +22,10 @@ Required Properties:
 
 - "renesas,r8a73a4-cmt0" for the 32-bit CMT0 device included in r8a73a4.
 - "renesas,r8a73a4-cmt1" for the 48-bit CMT1 device included in r8a73a4.
+- "renesas,r8a7740-cmt0" for the 32-bit CMT0 device included in r8a7740.
+- "renesas,r8a7740-cmt2" for the 32-bit CMT2 device included in r8a7740.
+- "renesas,r8a7740-cmt3" for the 32-bit CMT3 device included in r8a7740.
+- "renesas,r8a7740-cmt4" for the 32-bit CMT4 device included in r8a7740.
 - "renesas,r8a7743-cmt0" for the 32-bit CMT0 device included in r8a7743.
 - "renesas,r8a7743-cmt1" for the 48-bit CMT1 device included in r8a7743.
 - "renesas,r8a7744-cmt0" for the 32-bit CMT0 device included in r8a7744.
@@ -54,6 +58,10 @@ Required Properties:
 - "renesas,r8a77980-cmt1" for the 48-bit CMT1 device included in r8a77980.
 - "renesas,r8a77990-cmt0" for the 32-bit CMT0 device included in r8a77990.
 - "renesas,r8a77990-cmt1" for the 48-bit CMT1 device included in r8a77990.
+- "renesas,sh73a0-cmt0" for the 32-bit CMT0 device included in sh73a0.
+- "renesas,sh73a0-cmt2" for the 32-bit CMT2 device included in sh73a0.
+- "renesas,sh73a0-cmt3" for the 32-bit CMT3 device included in sh73a0.
+- "renesas,sh73a0-cmt4" for the 32-bit CMT4 device included in sh73a0.
 
 - "renesas,rcar-gen2-cmt0" for 32-bit CMT0 devices included in R-Car Gen2
and RZ/G1.


[PATCH 3/7] dt-bindings: timer: renesas, cmt: Add CMT0 and CMT1 to r8a7792

2019-07-18 Thread Magnus Damm
From: Magnus Damm 

This patch adds DT binding documentation for the CMT devices on
the R-Car Gen2 V2H (r8a7792) SoC.

Signed-off-by: Magnus Damm 
Reviewed-by: Geert Uytterhoeven 
Reviewed-by: Rob Herring 
---

 Documentation/devicetree/bindings/timer/renesas,cmt.txt |2 ++
 1 file changed, 2 insertions(+)

--- 0004/Documentation/devicetree/bindings/timer/renesas,cmt.txt
+++ work/Documentation/devicetree/bindings/timer/renesas,cmt.txt
2019-07-18 18:23:48.256013425 +0900
@@ -35,6 +35,8 @@ Required Properties:
 - "renesas,r8a7790-cmt1" for the 48-bit CMT1 device included in r8a7790.
 - "renesas,r8a7791-cmt0" for the 32-bit CMT0 device included in r8a7791.
 - "renesas,r8a7791-cmt1" for the 48-bit CMT1 device included in r8a7791.
+- "renesas,r8a7792-cmt0" for the 32-bit CMT0 device included in r8a7792.
+- "renesas,r8a7792-cmt1" for the 48-bit CMT1 device included in r8a7792.
 - "renesas,r8a7793-cmt0" for the 32-bit CMT0 device included in r8a7793.
 - "renesas,r8a7793-cmt1" for the 48-bit CMT1 device included in r8a7793.
 - "renesas,r8a7794-cmt0" for the 32-bit CMT0 device included in r8a7794.


[PATCH 0/7] renesas, cmt: DT Binding Documentation and Minor Driver Updates

2019-07-18 Thread Magnus Damm
renesas, cmt: DT Binding Documentation and Minor Driver Updates

[PATCH 1/7] dt-bindings: timer: renesas, cmt: Add CMT0234 to sh73a0 and r8a7740
[PATCH 2/7] dt-bindings: timer: renesas, cmt: Update CMT1 on sh73a0 and r8a7740
[PATCH 3/7] dt-bindings: timer: renesas, cmt: Add CMT0 and CMT1 to r8a7792
[PATCH 4/7] dt-bindings: timer: renesas, cmt: Add CMT0 and CMT1 to r8a77995
[PATCH 5/7] dt-bindings: timer: renesas, cmt: Update R-Car Gen3 CMT1 usage
[PATCH 6/7] clocksource/drivers/sh_cmt: r8a7740 and sh73a0 SoC-specific match
[PATCH 7/7] clocksource/drivers/sh_cmt: Document "cmt-48" as deprecated 

This series collect the following rather trivial changes for the CMT driver:
- Add 32-bit CMT0234 and convert CMT1 DT binding docs on sh73a0 and r8a7740.
- Add documentation for the CMT on the R-Car Gen2 V2H (r8a7792) SoC.
- Add missing R-Car Gen3 DT binding documentation for D3 (r8a77995).
- Update the R-Car Gen3 DT documentation to reflect current usage.
- Introduce SoC-specific matching in the driver for CMT1 on sh73a0 and sh73a0.
- Document old "cmt-48" binding as deprecated in the driver.

Please see each individual patch for more detailed information.

Signed-off-by: Magnus Damm 
Reviewed-by: Geert Uytterhoeven  [Patch 3-5]
Reviewed-by: Rob Herring  [Patch 1-5]
---

Developed on top of "renesas-devel-2019-07-08-v5.2" which includes
CMT DT Documentation patches queued for v5.3-rc

Earlier posted as:
[PATCH 0/8] dt-bindings: timer: renesas, cmt: Various updates
[PATCH 0/3] clocksource/drivers/sh_cmt: Minor DT compat string update

 Documentation/devicetree/bindings/timer/renesas,cmt.txt |   42 ---
 drivers/clocksource/sh_cmt.c|   14 -
 2 files changed, 37 insertions(+), 19 deletions(-)




Re: [PATCH v4 02/09] iommu/ipmmu-vmsa: Add optional root device feature

2017-10-16 Thread Magnus Damm
Hi Robin,

On Tue, Jun 20, 2017 at 2:19 AM, Robin Murphy  wrote:
> On 19/06/17 10:14, Magnus Damm wrote:
>> From: Magnus Damm 
>>
>> Add root device handling to the IPMMU driver by allowing certain
>> DT compat strings to enable has_cache_leaf_nodes that in turn will
>> support both root devices with interrupts and leaf devices that
>> face the actual IPMMU consumer devices.
>>
>> Signed-off-by: Magnus Damm 
>> ---
>>
>>  Changes since V3:
>>  - Reworked root finding code to make it easier to follow, thanks Geert!
>>
>>  Changes since V2:
>>  - Fixed a bug in ipmmu_find_root() when only leaf devices are present
>>  - Broke out __ipmmu_find_root() to allow ->xlate() check for root devices
>>
>>  Changes since V1:
>>  - Moved patch to earlier in the series
>>  - Updated code to work with recent changes in:
>>[PATCH v3 00/06] iommu/ipmmu-vmsa: IPMMU multi-arch update V3
>>
>>  drivers/iommu/ipmmu-vmsa.c |   95 
>> 
>>  1 file changed, 78 insertions(+), 17 deletions(-)
>>
>> --- 0015/drivers/iommu/ipmmu-vmsa.c
>> +++ work/drivers/iommu/ipmmu-vmsa.c   2017-06-19 13:59:41.050607110 +0900
>> @@ -36,6 +36,7 @@
>>
>>  struct ipmmu_features {
>>   bool use_ns_alias_offset;
>> + bool has_cache_leaf_nodes;
>>  };
>>
>>  struct ipmmu_vmsa_device {
>> @@ -44,6 +45,7 @@ struct ipmmu_vmsa_device {
>>   struct iommu_device iommu;
>>   struct list_head list;
>>   const struct ipmmu_features *features;
>> + bool is_leaf;
>>   unsigned int num_utlbs;
>>   spinlock_t lock;/* Protects ctx and domains[] 
>> */
>>   DECLARE_BITMAP(ctx, IPMMU_CTX_MAX);
>> @@ -54,6 +56,7 @@ struct ipmmu_vmsa_device {
>>
>>  struct ipmmu_vmsa_domain {
>>   struct ipmmu_vmsa_device *mmu;
>> + struct ipmmu_vmsa_device *root;
>
> Would it not make more sense for this to be a property of the
> ipmmu_device itself, rather than per ipmmu_domain? I may of course have
> got the wrong idea of the topology here, but it seems as if mmu->is_leaf
> could be expressed as mmu->root == mmu vs. mmu->root == some_other_mmu,
> at which point there's one less thing to worry about in the domain.

Yes, you are right! Please have a look at patch 2 in V5 that is doing that.

>>   struct iommu_domain io_domain;
>>
>>   struct io_pgtable_cfg cfg;
>> @@ -203,6 +206,44 @@ static struct ipmmu_vmsa_iommu_priv *to_
>>  #define IMUASID_ASID0_SHIFT  0
>>
>>  /* 
>> -
>> + * Root device handling
>> + */
>> +
>> +static bool ipmmu_is_root(struct ipmmu_vmsa_device *mmu)
>> +{
>> + if (mmu->features->has_cache_leaf_nodes)
>> + return mmu->is_leaf ? false : true> +   else
>> + return true; /* older IPMMU hardware treated as single root */
>> +}
>> +
>> +static struct ipmmu_vmsa_device *__ipmmu_find_root(void)
>> +{
>> + struct ipmmu_vmsa_device *mmu;
>> + struct ipmmu_vmsa_device *root = NULL;
>> +
>> + spin_lock(&ipmmu_devices_lock);
>> +
>> + list_for_each_entry(mmu, &ipmmu_devices, list) {
>> + if (ipmmu_is_root(mmu)) {
>> + root = mmu;
>> + break;
>> + }
>> + }
>> +
>> + spin_unlock(&ipmmu_devices_lock);
>> + return root;
>> +}
>
> I wonder if it might be tidier to use driver_for_each_device() for this,
> and remove the local list at the same time as its previous user.

Yep, also included in V5.

> Either way, what happens if things end up hapening in this order:
>
> 1: probe leaf IPMMU B
> 2: probe device X behind IPMMU B
> 3: create and attach default domain for device X
> 4: probe root IPMMU A
>
> We know X will defer if B isn't ready, but it doesn't seem (at a glance,
> admittedly) that there's anything to enforce the expected probe ordering
> between A and B. This seems like another argument for moving the
> root/leaf association up to the device level, such that B can look up A
> once in its own probe routine, and defer itself if necessary.

There used to be code to check for presence of root device inside
xlate() in "[PATCH v4 09/09] iommu/ipmmu-vmsa: Hook up r8a7795 DT
matching code" however in V5 I'm deferring probe of non-root devices
to handle this.

>> +
>> +static struct ipmmu_vmsa_device *ipmmu_find_

[PATCH v5 08/09] iommu/ipmmu-vmsa: Allow two bit SL0

2017-10-16 Thread Magnus Damm
From: Magnus Damm 

Introduce support for two bit SL0 bitfield in IMTTBCR
by using a separate feature flag.

Signed-off-by: Magnus Damm 
---

 Changes since V4:
 - Use leaf node mmu instead of root

 Changes since V3:
 - None

 Changes since V2:
 - None

 Changes since V1:
 - None

 drivers/iommu/ipmmu-vmsa.c |   14 +-
 1 file changed, 13 insertions(+), 1 deletion(-)

--- 0019/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-10-16 20:24:22.990607110 +0900
@@ -40,6 +40,7 @@ struct ipmmu_features {
bool has_cache_leaf_nodes;
unsigned int number_of_contexts;
bool setup_imbuscr;
+   bool twobit_imttbcr_sl0;
 };
 
 struct ipmmu_vmsa_device {
@@ -144,6 +145,10 @@ static struct ipmmu_vmsa_iommu_priv *to_
 #define IMTTBCR_TSZ0_MASK  (7 << 0)
 #define IMTTBCR_TSZ0_SHIFT O
 
+#define IMTTBCR_SL0_TWOBIT_LVL_3   (0 << 6)
+#define IMTTBCR_SL0_TWOBIT_LVL_2   (1 << 6)
+#define IMTTBCR_SL0_TWOBIT_LVL_1   (2 << 6)
+
 #define IMBUSCR0x000c
 #define IMBUSCR_DVM(1 << 2)
 #define IMBUSCR_BUSSEL_SYS (0 << 0)
@@ -396,6 +401,7 @@ static void ipmmu_domain_free_context(st
 static int ipmmu_domain_init_context(struct ipmmu_vmsa_domain *domain)
 {
u64 ttbr;
+   u32 tmp;
int ret;
 
/*
@@ -449,9 +455,14 @@ static int ipmmu_domain_init_context(str
 * We use long descriptors with inner-shareable WBWA tables and allocate
 * the whole 32-bit VA space to TTBR0.
 */
+   if (domain->mmu->features->twobit_imttbcr_sl0)
+   tmp = IMTTBCR_SL0_TWOBIT_LVL_1;
+   else
+   tmp = IMTTBCR_SL0_LVL_1;
+
ipmmu_ctx_write_root(domain, IMTTBCR, IMTTBCR_EAE |
 IMTTBCR_SH0_INNER_SHAREABLE | IMTTBCR_ORGN0_WB_WA |
-IMTTBCR_IRGN0_WB_WA | IMTTBCR_SL0_LVL_1);
+IMTTBCR_IRGN0_WB_WA | tmp);
 
/* MAIR0 */
ipmmu_ctx_write_root(domain, IMMAIR0,
@@ -982,6 +993,7 @@ static const struct ipmmu_features ipmmu
.has_cache_leaf_nodes = false,
.number_of_contexts = 1, /* software only tested with one context */
.setup_imbuscr = true,
+   .twobit_imttbcr_sl0 = false,
 };
 
 static const struct of_device_id ipmmu_of_ids[] = {


[PATCH v5 09/09] iommu/ipmmu-vmsa: Hook up r8a7795 DT matching code

2017-10-16 Thread Magnus Damm
From: Magnus Damm 

Tie in r8a7795 features and update the IOMMU_OF_DECLARE
compat string to include the updated compat string.

Signed-off-by: Magnus Damm 
---

 Changes since V4:
 - Got rid of root device availability check in ->xlate()
   -> deferred probing is used to make sure the root is always present

 Changes since V3:
 - Rebased code on top of
   [PATCH 00/04] iommu/ipmmu-vmsa: 32-bit ARM update
   This includes support for iommu_fwspec_add_ids()
 - Use dev_err() instead of dev_info() - Thanks Geert!
 - Moved single-invokation check into of_xlate() - Thanks Geert!
 - Dropped TODO list
 
 Changes since V2:
 - Check for lack of root device in ->xlate()
   This fixed a bug when IPMMU-MM is disabled in DT the system hangs on boot
 - Added code to ipmmu_init_platform_device() to handle multiple ->xlate() calls
 - Include empty white list by default
 - Updated TODO list

 Changes since V1:
 - Enable multi context feature
 - Update TODO list

 drivers/iommu/ipmmu-vmsa.c |   29 +
 1 file changed, 29 insertions(+)

--- 0019/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-10-16 19:53:14.710607110 +0900
@@ -25,6 +25,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #if defined(CONFIG_ARM) && !defined(CONFIG_IOMMU_DMA)
 #include 
@@ -735,9 +736,24 @@ static int ipmmu_init_platform_device(st
return 0;
 }
 
+static bool ipmmu_slave_whitelist(struct device *dev)
+{
+   /* By default, do not allow use of IPMMU */
+   return false;
+}
+
+static const struct soc_device_attribute soc_r8a7795[] = {
+   { .soc_id = "r8a7795", },
+   { /* sentinel */ }
+};
+
 static int ipmmu_of_xlate(struct device *dev,
  struct of_phandle_args *spec)
 {
+   /* For R-Car Gen3 use a white list to opt-in slave devices */
+   if (soc_device_match(soc_r8a7795) && !ipmmu_slave_whitelist(dev))
+   return -ENODEV;
+
iommu_fwspec_add_ids(dev, spec->args, 1);
 
/* Initialize once - xlate() will call multiple times */
@@ -996,11 +1012,22 @@ static const struct ipmmu_features ipmmu
.twobit_imttbcr_sl0 = false,
 };
 
+static const struct ipmmu_features ipmmu_features_r8a7795 = {
+   .use_ns_alias_offset = false,
+   .has_cache_leaf_nodes = true,
+   .number_of_contexts = 8,
+   .setup_imbuscr = false,
+   .twobit_imttbcr_sl0 = true,
+};
+
 static const struct of_device_id ipmmu_of_ids[] = {
{
.compatible = "renesas,ipmmu-vmsa",
.data = &ipmmu_features_default,
}, {
+   .compatible = "renesas,ipmmu-r8a7795",
+   .data = &ipmmu_features_r8a7795,
+   }, {
/* Terminator */
},
 };
@@ -1185,6 +1212,8 @@ static int __init ipmmu_vmsa_iommu_of_se
 
 IOMMU_OF_DECLARE(ipmmu_vmsa_iommu_of, "renesas,ipmmu-vmsa",
 ipmmu_vmsa_iommu_of_setup);
+IOMMU_OF_DECLARE(ipmmu_r8a7795_iommu_of, "renesas,ipmmu-r8a7795",
+ipmmu_vmsa_iommu_of_setup);
 #endif
 
 MODULE_DESCRIPTION("IOMMU API for Renesas VMSA-compatible IPMMU");


[PATCH v5 06/09] iommu/ipmmu-vmsa: Write IMCTR twice

2017-10-16 Thread Magnus Damm
From: Magnus Damm 

Write IMCTR both in the root device and the leaf node.

To allow access of IMCTR introduce the following function:
 - ipmmu_ctx_write_all()

While at it also rename context functions:
 - ipmmu_ctx_read() -> ipmmu_ctx_read_root()
 - ipmmu_ctx_write() -> ipmmu_ctx_write_root()

Signed-off-by: Magnus Damm 
---

 Changes since V4:
 - Updated to make use of new root pointer location

 Changes since V3:
 - Changed function names to improve code readability - Thanks Robin!

 Changes since V2:
 - None

 Changes since V1:
 - None

 drivers/iommu/ipmmu-vmsa.c |   56 +++-
 1 file changed, 35 insertions(+), 21 deletions(-)

--- 0015/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-10-16 19:50:19.240607110 +0900
@@ -248,19 +248,31 @@ static void ipmmu_write(struct ipmmu_vms
iowrite32(data, mmu->base + offset);
 }
 
-static u32 ipmmu_ctx_read(struct ipmmu_vmsa_domain *domain, unsigned int reg)
+static u32 ipmmu_ctx_read_root(struct ipmmu_vmsa_domain *domain,
+  unsigned int reg)
 {
return ipmmu_read(domain->mmu->root,
  domain->context_id * IM_CTX_SIZE + reg);
 }
 
-static void ipmmu_ctx_write(struct ipmmu_vmsa_domain *domain, unsigned int reg,
-   u32 data)
+static void ipmmu_ctx_write_root(struct ipmmu_vmsa_domain *domain,
+unsigned int reg, u32 data)
 {
ipmmu_write(domain->mmu->root,
domain->context_id * IM_CTX_SIZE + reg, data);
 }
 
+static void ipmmu_ctx_write_all(struct ipmmu_vmsa_domain *domain,
+   unsigned int reg, u32 data)
+{
+   if (domain->mmu != domain->mmu->root)
+   ipmmu_write(domain->mmu,
+   domain->context_id * IM_CTX_SIZE + reg, data);
+
+   ipmmu_write(domain->mmu->root,
+   domain->context_id * IM_CTX_SIZE + reg, data);
+}
+
 /* 
-
  * TLB and microTLB Management
  */
@@ -270,7 +282,7 @@ static void ipmmu_tlb_sync(struct ipmmu_
 {
unsigned int count = 0;
 
-   while (ipmmu_ctx_read(domain, IMCTR) & IMCTR_FLUSH) {
+   while (ipmmu_ctx_read_root(domain, IMCTR) & IMCTR_FLUSH) {
cpu_relax();
if (++count == TLB_LOOP_TIMEOUT) {
dev_err_ratelimited(domain->mmu->dev,
@@ -285,9 +297,9 @@ static void ipmmu_tlb_invalidate(struct
 {
u32 reg;
 
-   reg = ipmmu_ctx_read(domain, IMCTR);
+   reg = ipmmu_ctx_read_root(domain, IMCTR);
reg |= IMCTR_FLUSH;
-   ipmmu_ctx_write(domain, IMCTR, reg);
+   ipmmu_ctx_write_all(domain, IMCTR, reg);
 
ipmmu_tlb_sync(domain);
 }
@@ -428,31 +440,32 @@ static int ipmmu_domain_init_context(str
 
/* TTBR0 */
ttbr = domain->cfg.arm_lpae_s1_cfg.ttbr[0];
-   ipmmu_ctx_write(domain, IMTTLBR0, ttbr);
-   ipmmu_ctx_write(domain, IMTTUBR0, ttbr >> 32);
+   ipmmu_ctx_write_root(domain, IMTTLBR0, ttbr);
+   ipmmu_ctx_write_root(domain, IMTTUBR0, ttbr >> 32);
 
/*
 * TTBCR
 * We use long descriptors with inner-shareable WBWA tables and allocate
 * the whole 32-bit VA space to TTBR0.
 */
-   ipmmu_ctx_write(domain, IMTTBCR, IMTTBCR_EAE |
-   IMTTBCR_SH0_INNER_SHAREABLE | IMTTBCR_ORGN0_WB_WA |
-   IMTTBCR_IRGN0_WB_WA | IMTTBCR_SL0_LVL_1);
+   ipmmu_ctx_write_root(domain, IMTTBCR, IMTTBCR_EAE |
+IMTTBCR_SH0_INNER_SHAREABLE | IMTTBCR_ORGN0_WB_WA |
+IMTTBCR_IRGN0_WB_WA | IMTTBCR_SL0_LVL_1);
 
/* MAIR0 */
-   ipmmu_ctx_write(domain, IMMAIR0, domain->cfg.arm_lpae_s1_cfg.mair[0]);
+   ipmmu_ctx_write_root(domain, IMMAIR0,
+domain->cfg.arm_lpae_s1_cfg.mair[0]);
 
/* IMBUSCR */
-   ipmmu_ctx_write(domain, IMBUSCR,
-   ipmmu_ctx_read(domain, IMBUSCR) &
-   ~(IMBUSCR_DVM | IMBUSCR_BUSSEL_MASK));
+   ipmmu_ctx_write_root(domain, IMBUSCR,
+ipmmu_ctx_read_root(domain, IMBUSCR) &
+~(IMBUSCR_DVM | IMBUSCR_BUSSEL_MASK));
 
/*
 * IMSTR
 * Clear all interrupt flags.
 */
-   ipmmu_ctx_write(domain, IMSTR, ipmmu_ctx_read(domain, IMSTR));
+   ipmmu_ctx_write_root(domain, IMSTR, ipmmu_ctx_read_root(domain, IMSTR));
 
/*
 * IMCTR
@@ -461,7 +474,8 @@ static int ipmmu_domain_init_context(str
 * software management as we have no use for it. Flush the TLB as
 * required when modifying the context registers.
 */
-   ipmmu_ctx_write(domain, IMCTR, IMCTR_INTEN | IMCTR_FLUSH | IMCTR_MMUEN);
+   ipmmu_ct

[PATCH v5 07/09] iommu/ipmmu-vmsa: Make IMBUSCTR setup optional

2017-10-16 Thread Magnus Damm
From: Magnus Damm 

Introduce a feature to allow opt-out of setting up
IMBUSCR. The default case is unchanged.

Signed-off-by: Magnus Damm 
---

 Changes since V4:
 - Use leaf node mmu instead of root

 Changes since V3:
 - None

 Changes since V2:
 - None

 Changes since V1:
 - Updated the commit message
 - Reworked patch to coexist with the multi context feature


 drivers/iommu/ipmmu-vmsa.c |9 ++---
 1 file changed, 6 insertions(+), 3 deletions(-)

--- 0018/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-10-16 20:20:30.860607110 +0900
@@ -39,6 +39,7 @@ struct ipmmu_features {
bool use_ns_alias_offset;
bool has_cache_leaf_nodes;
unsigned int number_of_contexts;
+   bool setup_imbuscr;
 };
 
 struct ipmmu_vmsa_device {
@@ -457,9 +458,10 @@ static int ipmmu_domain_init_context(str
 domain->cfg.arm_lpae_s1_cfg.mair[0]);
 
/* IMBUSCR */
-   ipmmu_ctx_write_root(domain, IMBUSCR,
-ipmmu_ctx_read_root(domain, IMBUSCR) &
-~(IMBUSCR_DVM | IMBUSCR_BUSSEL_MASK));
+   if (domain->mmu->features->setup_imbuscr)
+   ipmmu_ctx_write_root(domain, IMBUSCR,
+ipmmu_ctx_read_root(domain, IMBUSCR) &
+~(IMBUSCR_DVM | IMBUSCR_BUSSEL_MASK));
 
/*
 * IMSTR
@@ -979,6 +981,7 @@ static const struct ipmmu_features ipmmu
.use_ns_alias_offset = true,
.has_cache_leaf_nodes = false,
.number_of_contexts = 1, /* software only tested with one context */
+   .setup_imbuscr = true,
 };
 
 static const struct of_device_id ipmmu_of_ids[] = {


[PATCH v5 05/09] iommu/ipmmu-vmsa: IPMMU device is 40-bit bus master

2017-10-16 Thread Magnus Damm
From: Magnus Damm 

The r8a7795 IPMMU supports 40-bit bus mastering. Both
the coherent DMA mask and the streaming DMA mask are
set to unlock the 40-bit address space for coherent
allocations and streaming operations.

Signed-off-by: Magnus Damm 
---

 Changes since V4:
 - None

 Changes since V3:
 - None

 Changes since V2:
 - Updated the code and commit message to use 40 bits instead of 64 bits

 Changes since V1:
 - Updated the commit message

 drivers/iommu/ipmmu-vmsa.c |1 +
 1 file changed, 1 insertion(+)

--- 0012/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-10-16 20:37:31.480607110 +0900
@@ -996,6 +996,7 @@ static int ipmmu_probe(struct platform_d
spin_lock_init(&mmu->lock);
bitmap_zero(mmu->ctx, IPMMU_CTX_MAX);
mmu->features = of_device_get_match_data(&pdev->dev);
+   dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(40));
 
/* Map I/O memory and request IRQ. */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);


[PATCH v5 04/09] iommu/ipmmu-vmsa: Make use of IOMMU_OF_DECLARE()

2017-10-16 Thread Magnus Damm
From: Magnus Damm 

Hook up IOMMU_OF_DECLARE() support in case CONFIG_IOMMU_DMA
is enabled. The only current supported case for 32-bit ARM
is disabled, however for 64-bit ARM usage of OF is required.

Signed-off-by: Magnus Damm 
---

 Changes since V4:
 - Use ipmmu_is_root() instead of now removed is_leaf flag

 Changes since V3:
 - Reworked to fit on top of
   [PATCH 00/04] iommu/ipmmu-vmsa: 32-bit ARM update

 Changes since V2:
 - Reworked registration code to make use of recently introduced:
 iommu_device_register()
 iommu_device_set_ops()
 iommu_device_set_fwnode()

 Changes since V1:
 - Reworked slightly to fit updated patch order and
   [PATCH v3 00/06] iommu/ipmmu-vmsa: IPMMU multi-arch update V3


 drivers/iommu/ipmmu-vmsa.c |   50 
 1 file changed, 41 insertions(+), 9 deletions(-)

--- 0014/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-10-16 19:59:42.700607110 +0900
@@ -20,6 +20,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -1055,17 +1056,30 @@ static int ipmmu_probe(struct platform_d
ipmmu_device_reset(mmu);
}
 
-   ret = iommu_device_sysfs_add(&mmu->iommu, &pdev->dev, NULL,
-dev_name(&pdev->dev));
-   if (ret)
-   return ret;
+   /*
+* Register the IPMMU to the IOMMU subsystem in the following cases:
+* - R-Car Gen2 IPMMU (all devices registered)
+* - R-Car Gen3 IPMMU (leaf devices only - skip root IPMMU-MM device)
+*/
+   if (!mmu->features->has_cache_leaf_nodes || !ipmmu_is_root(mmu)) {
+   ret = iommu_device_sysfs_add(&mmu->iommu, &pdev->dev, NULL,
+dev_name(&pdev->dev));
+   if (ret)
+   return ret;
 
-   iommu_device_set_ops(&mmu->iommu, &ipmmu_ops);
-   iommu_device_set_fwnode(&mmu->iommu, &pdev->dev.of_node->fwnode);
+   iommu_device_set_ops(&mmu->iommu, &ipmmu_ops);
+   iommu_device_set_fwnode(&mmu->iommu,
+   &pdev->dev.of_node->fwnode);
 
-   ret = iommu_device_register(&mmu->iommu);
-   if (ret)
-   return ret;
+   ret = iommu_device_register(&mmu->iommu);
+   if (ret)
+   return ret;
+
+#if defined(CONFIG_IOMMU_DMA)
+   if (!iommu_present(&platform_bus_type))
+   bus_set_iommu(&platform_bus_type, &ipmmu_ops);
+#endif
+   }
 
/*
 * We can't create the ARM mapping here as it requires the bus to have
@@ -1105,15 +1119,22 @@ static struct platform_driver ipmmu_driv
 
 static int __init ipmmu_init(void)
 {
+   static bool setup_done;
int ret;
 
+   if (setup_done)
+   return 0;
+
ret = platform_driver_register(&ipmmu_driver);
if (ret < 0)
return ret;
 
+#if defined(CONFIG_ARM) && !defined(CONFIG_IOMMU_DMA)
if (!iommu_present(&platform_bus_type))
bus_set_iommu(&platform_bus_type, &ipmmu_ops);
+#endif
 
+   setup_done = true;
return 0;
 }
 
@@ -1125,6 +1146,17 @@ static void __exit ipmmu_exit(void)
 subsys_initcall(ipmmu_init);
 module_exit(ipmmu_exit);
 
+#ifdef CONFIG_IOMMU_DMA
+static int __init ipmmu_vmsa_iommu_of_setup(struct device_node *np)
+{
+   ipmmu_init();
+   return 0;
+}
+
+IOMMU_OF_DECLARE(ipmmu_vmsa_iommu_of, "renesas,ipmmu-vmsa",
+ipmmu_vmsa_iommu_of_setup);
+#endif
+
 MODULE_DESCRIPTION("IOMMU API for Renesas VMSA-compatible IPMMU");
 MODULE_AUTHOR("Laurent Pinchart ");
 MODULE_LICENSE("GPL v2");


[PATCH v5 03/09] iommu/ipmmu-vmsa: Enable multi context support

2017-10-16 Thread Magnus Damm
From: Magnus Damm 

Add support for up to 8 contexts. Each context is mapped to one
domain. One domain is assigned one or more slave devices. Contexts
are allocated dynamically and slave devices are grouped together
based on which IPMMU device they are connected to. This makes slave
devices tied to the same IPMMU device share the same IOVA space.

Signed-off-by: Magnus Damm 
---

 Changes since V4:
 - None

 Changes since V3:
 - Use number_of_contexts unsigned int, drop WARN_ON() - Thanks Robin!

 Changes since V2:
 - Updated patch description to reflect code included in:
   [PATCH v7 00/07] iommu/ipmmu-vmsa: IPMMU multi-arch update V7

 Changes since V1:
 - Support up to 8 contexts instead of 4
 - Use feature flag and runtime handling
 - Default to single context

 drivers/iommu/ipmmu-vmsa.c |   30 ++
 1 file changed, 22 insertions(+), 8 deletions(-)

--- 0011/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-10-16 19:46:09.900607110 +0900
@@ -32,11 +32,12 @@
 
 #include "io-pgtable.h"
 
-#define IPMMU_CTX_MAX 1
+#define IPMMU_CTX_MAX 8
 
 struct ipmmu_features {
bool use_ns_alias_offset;
bool has_cache_leaf_nodes;
+   unsigned int number_of_contexts;
 };
 
 struct ipmmu_vmsa_device {
@@ -46,6 +47,7 @@ struct ipmmu_vmsa_device {
struct ipmmu_vmsa_device *root;
const struct ipmmu_features *features;
unsigned int num_utlbs;
+   unsigned int num_ctx;
spinlock_t lock;/* Protects ctx and domains[] */
DECLARE_BITMAP(ctx, IPMMU_CTX_MAX);
struct ipmmu_vmsa_domain *domains[IPMMU_CTX_MAX];
@@ -352,11 +354,12 @@ static int ipmmu_domain_allocate_context
 
spin_lock_irqsave(&mmu->lock, flags);
 
-   ret = find_first_zero_bit(mmu->ctx, IPMMU_CTX_MAX);
-   if (ret != IPMMU_CTX_MAX) {
+   ret = find_first_zero_bit(mmu->ctx, mmu->num_ctx);
+   if (ret != mmu->num_ctx) {
mmu->domains[ret] = domain;
set_bit(ret, mmu->ctx);
-   }
+   } else
+   ret = -EBUSY;
 
spin_unlock_irqrestore(&mmu->lock, flags);
 
@@ -409,8 +412,8 @@ static int ipmmu_domain_init_context(str
 * Find an unused context.
 */
ret = ipmmu_domain_allocate_context(domain->mmu->root, domain);
-   if (ret == IPMMU_CTX_MAX)
-   return -EBUSY;
+   if (ret < 0)
+   return ret;
 
domain->context_id = ret;
 
@@ -539,7 +542,7 @@ static irqreturn_t ipmmu_irq(int irq, vo
/*
 * Check interrupts for all active contexts.
 */
-   for (i = 0; i < IPMMU_CTX_MAX; i++) {
+   for (i = 0; i < mmu->num_ctx; i++) {
if (!mmu->domains[i])
continue;
if (ipmmu_domain_irq(mmu->domains[i]) == IRQ_HANDLED)
@@ -603,6 +606,13 @@ static int ipmmu_attach_device(struct io
/* The domain hasn't been used yet, initialize it. */
domain->mmu = mmu;
ret = ipmmu_domain_init_context(domain);
+   if (ret < 0) {
+   dev_err(dev, "Unable to initialize IPMMU context\n");
+   domain->mmu = NULL;
+   } else {
+   dev_info(dev, "Using IPMMU context %u\n",
+domain->context_id);
+   }
} else if (domain->mmu != mmu) {
/*
 * Something is wrong, we can't attach two devices using
@@ -946,13 +956,14 @@ static void ipmmu_device_reset(struct ip
unsigned int i;
 
/* Disable all contexts. */
-   for (i = 0; i < 4; ++i)
+   for (i = 0; i < mmu->num_ctx; ++i)
ipmmu_write(mmu, i * IM_CTX_SIZE + IMCTR, 0);
 }
 
 static const struct ipmmu_features ipmmu_features_default = {
.use_ns_alias_offset = true,
.has_cache_leaf_nodes = false,
+   .number_of_contexts = 1, /* software only tested with one context */
 };
 
 static const struct of_device_id ipmmu_of_ids[] = {
@@ -1006,6 +1017,9 @@ static int ipmmu_probe(struct platform_d
if (mmu->features->use_ns_alias_offset)
mmu->base += IM_NS_ALIAS_OFFSET;
 
+   mmu->num_ctx = min_t(unsigned int, IPMMU_CTX_MAX,
+mmu->features->number_of_contexts);
+
irq = platform_get_irq(pdev, 0);
 
/*


[PATCH v5 02/09] iommu/ipmmu-vmsa: Add optional root device feature

2017-10-16 Thread Magnus Damm
From: Magnus Damm 

Add root device handling to the IPMMU driver by allowing certain
DT compat strings to enable has_cache_leaf_nodes that in turn will
support both root devices with interrupts and leaf devices that
face the actual IPMMU consumer devices.

Signed-off-by: Magnus Damm 
---

 Changes since V4: (Many thanks to Robin for feedback)
 - Put the root pointer under struct ipmmu_vmsa_device
 - Drop is_leaf flag
 - Use driver_for_each_device instead of local list of devices
 - Return -EPROBE_DEFER to hook up root device first

 Changes since V3:
 - Reworked root finding code to make it easier to follow, thanks Geert!
 
 Changes since V2:
 - Fixed a bug in ipmmu_find_root() when only leaf devices are present
 - Broke out __ipmmu_find_root() to allow ->xlate() check for root devices

 Changes since V1:
 - Moved patch to earlier in the series
 - Updated code to work with recent changes in:
   [PATCH v3 00/06] iommu/ipmmu-vmsa: IPMMU multi-arch update V3

 drivers/iommu/ipmmu-vmsa.c |   90 +++-
 1 file changed, 73 insertions(+), 17 deletions(-)

--- 0009/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-10-16 19:43:27.020607110 +0900
@@ -36,12 +36,14 @@
 
 struct ipmmu_features {
bool use_ns_alias_offset;
+   bool has_cache_leaf_nodes;
 };
 
 struct ipmmu_vmsa_device {
struct device *dev;
void __iomem *base;
struct iommu_device iommu;
+   struct ipmmu_vmsa_device *root;
const struct ipmmu_features *features;
unsigned int num_utlbs;
spinlock_t lock;/* Protects ctx and domains[] */
@@ -199,6 +201,36 @@ static struct ipmmu_vmsa_iommu_priv *to_
 #define IMUASID_ASID0_SHIFT0
 
 /* 
-
+ * Root device handling
+ */
+
+static struct platform_driver ipmmu_driver;
+
+static bool ipmmu_is_root(struct ipmmu_vmsa_device *mmu)
+{
+   return mmu->root == mmu;
+}
+
+static int __ipmmu_check_device(struct device *dev, void *data)
+{
+   struct ipmmu_vmsa_device *mmu = dev_get_drvdata(dev);
+   struct ipmmu_vmsa_device **rootp = data;
+
+   if (ipmmu_is_root(mmu))
+   *rootp = mmu;
+
+   return 0;
+}
+
+static struct ipmmu_vmsa_device *ipmmu_find_root(void)
+{
+   struct ipmmu_vmsa_device *root = NULL;
+
+   return driver_for_each_device(&ipmmu_driver.driver, NULL, &root,
+ __ipmmu_check_device) == 0 ? root : NULL;
+}
+
+/* 
-
  * Read/Write Access
  */
 
@@ -215,13 +247,15 @@ static void ipmmu_write(struct ipmmu_vms
 
 static u32 ipmmu_ctx_read(struct ipmmu_vmsa_domain *domain, unsigned int reg)
 {
-   return ipmmu_read(domain->mmu, domain->context_id * IM_CTX_SIZE + reg);
+   return ipmmu_read(domain->mmu->root,
+ domain->context_id * IM_CTX_SIZE + reg);
 }
 
 static void ipmmu_ctx_write(struct ipmmu_vmsa_domain *domain, unsigned int reg,
u32 data)
 {
-   ipmmu_write(domain->mmu, domain->context_id * IM_CTX_SIZE + reg, data);
+   ipmmu_write(domain->mmu->root,
+   domain->context_id * IM_CTX_SIZE + reg, data);
 }
 
 /* 
-
@@ -369,12 +403,12 @@ static int ipmmu_domain_init_context(str
 * TODO: Add support for coherent walk through CCI with DVM and remove
 * cache handling. For now, delegate it to the io-pgtable code.
 */
-   domain->cfg.iommu_dev = domain->mmu->dev;
+   domain->cfg.iommu_dev = domain->mmu->root->dev;
 
/*
 * Find an unused context.
 */
-   ret = ipmmu_domain_allocate_context(domain->mmu, domain);
+   ret = ipmmu_domain_allocate_context(domain->mmu->root, domain);
if (ret == IPMMU_CTX_MAX)
return -EBUSY;
 
@@ -383,7 +417,8 @@ static int ipmmu_domain_init_context(str
domain->iop = alloc_io_pgtable_ops(ARM_32_LPAE_S1, &domain->cfg,
   domain);
if (!domain->iop) {
-   ipmmu_domain_free_context(domain->mmu, domain->context_id);
+   ipmmu_domain_free_context(domain->mmu->root,
+ domain->context_id);
return -EINVAL;
}
 
@@ -437,7 +472,7 @@ static void ipmmu_domain_destroy_context
 */
ipmmu_ctx_write(domain, IMCTR, IMCTR_FLUSH);
ipmmu_tlb_sync(domain);
-   ipmmu_domain_free_context(domain->mmu, domain->context_id);
+   ipmmu_domain_free_context(domain->mmu->root, domain->context_id);
 }
 
 /* 
-
@@ -

[PATCH v5 01/09] iommu/ipmmu-vmsa: Introduce features, break out alias

2017-10-16 Thread Magnus Damm
From: Magnus Damm 

Introduce struct ipmmu_features to track various hardware
and software implementation changes inside the driver for
different kinds of IPMMU hardware. Add use_ns_alias_offset
as a first example of a feature to control if the secure
register bank offset should be used or not.

Signed-off-by: Magnus Damm 
---

 Changes since V4:
 - None

 Changes since V3:
 - Use of_device_get_match_data(), thanks Robin!

 Changes since V2:
 - None

 Changes since V1:
 - Moved patch to front of the series


 drivers/iommu/ipmmu-vmsa.c |   31 ---
 1 file changed, 24 insertions(+), 7 deletions(-)

--- 0001/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-10-12 15:16:43.510607110 +0900
@@ -19,6 +19,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -33,11 +34,15 @@
 
 #define IPMMU_CTX_MAX 1
 
+struct ipmmu_features {
+   bool use_ns_alias_offset;
+};
+
 struct ipmmu_vmsa_device {
struct device *dev;
void __iomem *base;
struct iommu_device iommu;
-
+   const struct ipmmu_features *features;
unsigned int num_utlbs;
spinlock_t lock;/* Protects ctx and domains[] */
DECLARE_BITMAP(ctx, IPMMU_CTX_MAX);
@@ -910,6 +915,21 @@ static void ipmmu_device_reset(struct ip
ipmmu_write(mmu, i * IM_CTX_SIZE + IMCTR, 0);
 }
 
+static const struct ipmmu_features ipmmu_features_default = {
+   .use_ns_alias_offset = true,
+};
+
+static const struct of_device_id ipmmu_of_ids[] = {
+   {
+   .compatible = "renesas,ipmmu-vmsa",
+   .data = &ipmmu_features_default,
+   }, {
+   /* Terminator */
+   },
+};
+
+MODULE_DEVICE_TABLE(of, ipmmu_of_ids);
+
 static int ipmmu_probe(struct platform_device *pdev)
 {
struct ipmmu_vmsa_device *mmu;
@@ -927,6 +947,7 @@ static int ipmmu_probe(struct platform_d
mmu->num_utlbs = 32;
spin_lock_init(&mmu->lock);
bitmap_zero(mmu->ctx, IPMMU_CTX_MAX);
+   mmu->features = of_device_get_match_data(&pdev->dev);
 
/* Map I/O memory and request IRQ. */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -946,7 +967,8 @@ static int ipmmu_probe(struct platform_d
 * Offset the registers base unconditionally to point to the non-secure
 * alias space for now.
 */
-   mmu->base += IM_NS_ALIAS_OFFSET;
+   if (mmu->features->use_ns_alias_offset)
+   mmu->base += IM_NS_ALIAS_OFFSET;
 
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
@@ -1002,11 +1024,6 @@ static int ipmmu_remove(struct platform_
return 0;
 }
 
-static const struct of_device_id ipmmu_of_ids[] = {
-   { .compatible = "renesas,ipmmu-vmsa", },
-   { }
-};
-
 static struct platform_driver ipmmu_driver = {
.driver = {
.name = "ipmmu-vmsa",


[PATCH v5 00/09] iommu/ipmmu-vmsa: r8a7795 support V5

2017-10-16 Thread Magnus Damm
iommu/ipmmu-vmsa: r8a7795 support V5

[PATCH v5 01/09] iommu/ipmmu-vmsa: Introduce features, break out alias
[PATCH v5 02/09] iommu/ipmmu-vmsa: Add optional root device feature
[PATCH v5 03/09] iommu/ipmmu-vmsa: Enable multi context support
[PATCH v5 04/09] iommu/ipmmu-vmsa: Make use of IOMMU_OF_DECLARE()
[PATCH v5 05/09] iommu/ipmmu-vmsa: IPMMU device is 40-bit bus master
[PATCH v5 06/09] iommu/ipmmu-vmsa: Write IMCTR twice
[PATCH v5 07/09] iommu/ipmmu-vmsa: Make IMBUSCTR setup optional
[PATCH v5 08/09] iommu/ipmmu-vmsa: Allow two bit SL0
[PATCH v5 09/09] iommu/ipmmu-vmsa: Hook up r8a7795 DT matching code

This is V5 of r8a7795 IPMMU driver where the series has been rebased
and reworked to fit on next-20171013 that includes:
[PATCH v2 00/05] iommu/ipmmu-vmsa: 32-bit ARM update V2
[PATCH] iommu/ipmmu-vmsa: Use iommu_device_sysfs_add()/remove()

The major feature change is in patch 2/9 that now gets by without
using a local list of registered IPMMU devices and instead relies
on driver_for_each_device(). Thanks to Robin Murphy for his support.

The DT binding for r8a7795 has been accepted for upstream merge
and this series implements support following such format:

d4e42e7 iommu/ipmmu-vmsa: Add r8a7795 DT binding

The r8a7795 IPMMU is almost register compatible with earlier devices
like r8a7790-r8a7794, however some bitfields have been shifted
slightly. On a grander scale topology has been added and interrupts
have been reworked. So now there are several "cache" IPMMU units
without interrupt that somehow communicate with IPMMU-MM that
is the only instance that supports interrupts. The code refers to
IPMMU-MM as a "root" device and the other ones as "leaf" nodes.

Changes since V4:
 - Rebased on top of [PATCH v2 00/05] iommu/ipmmu-vmsa: 32-bit ARM update V2
 - Reworked root device handling to make use of driver_for_each_device()
 - Added deferred probing to make sure root device always is present

Signed-off-by: Magnus Damm 
---

 Developed on top of next-20171013
 Also applies to renesas-drivers-2017-10-03-v4.14-rc3
 Tested on top of renesas-drivers on r8a7796-m3ulcb using /dev/ttySC1
  - [PATCH v4 0/3] iommu/ipmmu-vmsa: r8a7796 support V4
  - local /dev/ttySC1 enablement for testing purpose
  - local DTS changes to hook up SYS-DMAC and IPMMU DS0, DS1 and MM
  - local whitelist code to enable "e731.dma-controller"
 
 drivers/iommu/ipmmu-vmsa.c |  310 ++--
 1 file changed, 244 insertions(+), 66 deletions(-)


[PATCH] iommu/ipmmu-vmsa: Use iommu_device_sysfs_add()/remove()

2017-08-20 Thread Magnus Damm
From: Magnus Damm 

Extend the driver to make use of iommu_device_sysfs_add()/remove()
functions to hook up initial sysfs support.

Suggested-by: Joerg Roedel 
Signed-off-by: Magnus Damm 
---

 Applies on top of next-20170817

 drivers/iommu/ipmmu-vmsa.c |6 ++
 1 file changed, 6 insertions(+)

--- 0001/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-08-21 14:40:13.940607110 +0900
@@ -953,6 +953,11 @@ static int ipmmu_probe(struct platform_d
 
ipmmu_device_reset(mmu);
 
+   ret = iommu_device_sysfs_add(&mmu->iommu, &pdev->dev, NULL,
+dev_name(&pdev->dev));
+   if (ret)
+   return ret;
+
iommu_device_set_ops(&mmu->iommu, &ipmmu_ops);
iommu_device_set_fwnode(&mmu->iommu, &pdev->dev.of_node->fwnode);
 
@@ -975,6 +980,7 @@ static int ipmmu_remove(struct platform_
 {
struct ipmmu_vmsa_device *mmu = platform_get_drvdata(pdev);
 
+   iommu_device_sysfs_remove(&mmu->iommu);
iommu_device_unregister(&mmu->iommu);
 
 #if defined(CONFIG_ARM) && !defined(CONFIG_IOMMU_DMA)


[PATCH v2 03/05] iommu/ipmmu-vmsa: Use fwspec on both 32 and 64-bit ARM

2017-07-17 Thread Magnus Damm
From: Robin Murphy 

Consolidate the 32-bit and 64-bit code to make use of fwspec instead
of archdata for the 32-bit ARM case.

This is a simplified version of the fwspec handling code from Robin
posted as [PATCH] iommu/ipmmu-vmsa: Convert to iommu_fwspec

Signed-off-by: Robin Murphy 
Signed-off-by: Magnus Damm 
---

 Changes since V1:
 - Rebased to apply on top of earlier changes in series

 drivers/iommu/ipmmu-vmsa.c |   21 +++--
 1 file changed, 3 insertions(+), 18 deletions(-)

--- 0004/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-07-17 21:04:54.850607110 +0900
@@ -73,22 +73,9 @@ static struct ipmmu_vmsa_domain *to_vmsa
return container_of(dom, struct ipmmu_vmsa_domain, io_domain);
 }
 
-
 static struct ipmmu_vmsa_iommu_priv *to_priv(struct device *dev)
 {
-#if defined(CONFIG_ARM)
-   return dev->archdata.iommu;
-#else
-   return dev->iommu_fwspec->iommu_priv;
-#endif
-}
-static void set_priv(struct device *dev, struct ipmmu_vmsa_iommu_priv *p)
-{
-#if defined(CONFIG_ARM)
-   dev->archdata.iommu = p;
-#else
-   dev->iommu_fwspec->iommu_priv = p;
-#endif
+   return dev->iommu_fwspec ? dev->iommu_fwspec->iommu_priv : NULL;
 }
 
 #define TLB_LOOP_TIMEOUT   100 /* 100us */
@@ -726,7 +713,7 @@ static int ipmmu_init_platform_device(st
priv->utlbs = utlbs;
priv->num_utlbs = num_utlbs;
priv->dev = dev;
-   set_priv(dev, priv);
+   dev->iommu_fwspec->iommu_priv = priv;
return 0;
 
 error:
@@ -887,14 +874,12 @@ static void ipmmu_domain_free_dma(struct
 
 static int ipmmu_add_device_dma(struct device *dev)
 {
-   struct iommu_fwspec *fwspec = dev->iommu_fwspec;
struct iommu_group *group;
 
/*
 * Only let through devices that have been verified in xlate()
-* We may get called with dev->iommu_fwspec set to NULL.
 */
-   if (!fwspec || !fwspec->iommu_priv)
+   if (!to_priv(dev))
return -ENODEV;
 
group = iommu_group_get_for_dev(dev);


[PATCH v2 04/05] iommu/ipmmu-vmsa: Replace local utlb code with fwspec ids

2017-07-17 Thread Magnus Damm
From: Magnus Damm 

Now when both 32-bit and 64-bit code inside the driver is using
fwspec it is possible to replace the utlb handling with fwspec ids
that get populated from ->of_xlate().

Suggested-by: Robin Murphy 
Signed-off-by: Magnus Damm 
---

 Changes since V1:
 - Rebased to apply on top of earlier changes in series

 drivers/iommu/ipmmu-vmsa.c |  104 
 1 file changed, 19 insertions(+), 85 deletions(-)

--- 0006/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-07-17 21:12:11.650607110 +0900
@@ -19,6 +19,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -59,8 +60,6 @@ struct ipmmu_vmsa_domain {
 
 struct ipmmu_vmsa_iommu_priv {
struct ipmmu_vmsa_device *mmu;
-   unsigned int *utlbs;
-   unsigned int num_utlbs;
struct device *dev;
struct list_head list;
 };
@@ -550,13 +549,14 @@ static int ipmmu_attach_device(struct io
   struct device *dev)
 {
struct ipmmu_vmsa_iommu_priv *priv = to_priv(dev);
+   struct iommu_fwspec *fwspec = dev->iommu_fwspec;
struct ipmmu_vmsa_device *mmu = priv->mmu;
struct ipmmu_vmsa_domain *domain = to_vmsa_domain(io_domain);
unsigned long flags;
unsigned int i;
int ret = 0;
 
-   if (!mmu) {
+   if (!priv || !priv->mmu) {
dev_err(dev, "Cannot attach to IPMMU\n");
return -ENXIO;
}
@@ -583,8 +583,8 @@ static int ipmmu_attach_device(struct io
if (ret < 0)
return ret;
 
-   for (i = 0; i < priv->num_utlbs; ++i)
-   ipmmu_utlb_enable(domain, priv->utlbs[i]);
+   for (i = 0; i < fwspec->num_ids; ++i)
+   ipmmu_utlb_enable(domain, fwspec->ids[i]);
 
return 0;
 }
@@ -592,12 +592,12 @@ static int ipmmu_attach_device(struct io
 static void ipmmu_detach_device(struct iommu_domain *io_domain,
struct device *dev)
 {
-   struct ipmmu_vmsa_iommu_priv *priv = to_priv(dev);
+   struct iommu_fwspec *fwspec = dev->iommu_fwspec;
struct ipmmu_vmsa_domain *domain = to_vmsa_domain(io_domain);
unsigned int i;
 
-   for (i = 0; i < priv->num_utlbs; ++i)
-   ipmmu_utlb_disable(domain, priv->utlbs[i]);
+   for (i = 0; i < fwspec->num_ids; ++i)
+   ipmmu_utlb_disable(domain, fwspec->ids[i]);
 
/*
 * TODO: Optimize by disabling the context when no device is attached.
@@ -633,102 +633,36 @@ static phys_addr_t ipmmu_iova_to_phys(st
return domain->iop->iova_to_phys(domain->iop, iova);
 }
 
-static int ipmmu_find_utlbs(struct ipmmu_vmsa_device *mmu, struct device *dev,
-   unsigned int *utlbs, unsigned int num_utlbs)
-{
-   unsigned int i;
-
-   for (i = 0; i < num_utlbs; ++i) {
-   struct of_phandle_args args;
-   int ret;
-
-   ret = of_parse_phandle_with_args(dev->of_node, "iommus",
-"#iommu-cells", i, &args);
-   if (ret < 0)
-   return ret;
-
-   of_node_put(args.np);
-
-   if (args.np != mmu->dev->of_node || args.args_count != 1)
-   return -EINVAL;
-
-   utlbs[i] = args.args[0];
-   }
-
-   return 0;
-}
-
-static int ipmmu_init_platform_device(struct device *dev)
+static int ipmmu_init_platform_device(struct device *dev,
+ struct of_phandle_args *args)
 {
+   struct platform_device *ipmmu_pdev;
struct ipmmu_vmsa_iommu_priv *priv;
-   struct ipmmu_vmsa_device *mmu;
-   unsigned int *utlbs;
-   unsigned int i;
-   int num_utlbs;
-   int ret = -ENODEV;
-
-   /* Find the master corresponding to the device. */
 
-   num_utlbs = of_count_phandle_with_args(dev->of_node, "iommus",
-  "#iommu-cells");
-   if (num_utlbs < 0)
+   ipmmu_pdev = of_find_device_by_node(args->np);
+   if (!ipmmu_pdev)
return -ENODEV;
 
-   utlbs = kcalloc(num_utlbs, sizeof(*utlbs), GFP_KERNEL);
-   if (!utlbs)
-   return -ENOMEM;
-
-   spin_lock(&ipmmu_devices_lock);
-
-   list_for_each_entry(mmu, &ipmmu_devices, list) {
-   ret = ipmmu_find_utlbs(mmu, dev, utlbs, num_utlbs);
-   if (!ret) {
-   /*
-* TODO Take a reference to the MMU to protect
-* against device removal.
-*/
-   break;
-   }
-   }
-
-   spin_unlock(&ipmmu_devices_lock);
-
-   if (ret < 0)
-   goto error;
-
-   f

[PATCH v2 05/05] iommu/ipmmu-vmsa: Clean up device tracking

2017-07-17 Thread Magnus Damm
From: Robin Murphy 

Get rid of now unused device tracking code. Future code should instead
be able to use driver_for_each_device() for this purpose.

This is a simplified version of the following patch from Robin
[PATCH] iommu/ipmmu-vmsa: Clean up group allocation

Signed-off-by: Robin Murphy 
Signed-off-by: Magnus Damm 
---

 Change since V1:
 - New patch

 drivers/iommu/ipmmu-vmsa.c |   12 
 1 file changed, 12 deletions(-)

--- 0008/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-07-17 21:35:26.690607110 +0900
@@ -37,7 +37,6 @@ struct ipmmu_vmsa_device {
struct device *dev;
void __iomem *base;
struct iommu_device iommu;
-   struct list_head list;
 
unsigned int num_utlbs;
spinlock_t lock;/* Protects ctx and domains[] */
@@ -64,9 +63,6 @@ struct ipmmu_vmsa_iommu_priv {
struct list_head list;
 };
 
-static DEFINE_SPINLOCK(ipmmu_devices_lock);
-static LIST_HEAD(ipmmu_devices);
-
 static struct ipmmu_vmsa_domain *to_vmsa_domain(struct iommu_domain *dom)
 {
return container_of(dom, struct ipmmu_vmsa_domain, io_domain);
@@ -970,10 +966,6 @@ static int ipmmu_probe(struct platform_d
 * ipmmu_init() after the probe function returns.
 */
 
-   spin_lock(&ipmmu_devices_lock);
-   list_add(&mmu->list, &ipmmu_devices);
-   spin_unlock(&ipmmu_devices_lock);
-
platform_set_drvdata(pdev, mmu);
 
return 0;
@@ -983,10 +975,6 @@ static int ipmmu_remove(struct platform_
 {
struct ipmmu_vmsa_device *mmu = platform_get_drvdata(pdev);
 
-   spin_lock(&ipmmu_devices_lock);
-   list_del(&mmu->list);
-   spin_unlock(&ipmmu_devices_lock);
-
iommu_device_unregister(&mmu->iommu);
 
 #if defined(CONFIG_ARM) && !defined(CONFIG_IOMMU_DMA)


[PATCH v2 02/05] iommu/ipmmu-vmsa: Consistent ->of_xlate() handling

2017-07-17 Thread Magnus Damm
From: Magnus Damm 

The 32-bit ARM code gets updated to make use of ->of_xlate() and the
code is shared between 64-bit and 32-bit ARM. The of_device_is_available()
check gets dropped since it is included in of_iommu_xlate().

Suggested-by: Robin Murphy 
Signed-off-by: Magnus Damm 
---

 Changes since V1:
 - Moved "Initialize once" check to ipmmu_of_xlate() - thanks Geert!

 drivers/iommu/ipmmu-vmsa.c |   51 ++--
 1 file changed, 17 insertions(+), 34 deletions(-)

--- 0002/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-07-17 21:03:38.340607110 +0900
@@ -734,6 +734,16 @@ error:
return ret;
 }
 
+static int ipmmu_of_xlate(struct device *dev,
+ struct of_phandle_args *spec)
+{
+   /* Initialize once - xlate() will call multiple times */
+   if (to_priv(dev))
+   return 0;
+
+   return ipmmu_init_platform_device(dev);
+}
+
 #if defined(CONFIG_ARM) && !defined(CONFIG_IOMMU_DMA)
 
 static struct iommu_domain *ipmmu_domain_alloc(unsigned type)
@@ -750,11 +760,11 @@ static int ipmmu_add_device(struct devic
struct iommu_group *group;
int ret;
 
-   if (to_priv(dev)) {
-   dev_warn(dev, "IOMMU driver already assigned to device %s\n",
-dev_name(dev));
-   return -EINVAL;
-   }
+   /*
+* Only let through devices that have been verified in xlate()
+*/
+   if (!to_priv(dev))
+   return -ENODEV;
 
/* Create a device group and add the device to it. */
group = iommu_group_alloc();
@@ -773,10 +783,6 @@ static int ipmmu_add_device(struct devic
goto error;
}
 
-   ret = ipmmu_init_platform_device(dev);
-   if (ret < 0)
-   goto error;
-
/*
 * Create the ARM mapping, used by the ARM DMA mapping core to allocate
 * VAs. This will allocate a corresponding IOMMU domain.
@@ -817,24 +823,13 @@ error:
if (!IS_ERR_OR_NULL(group))
iommu_group_remove_device(dev);
 
-   kfree(to_priv(dev)->utlbs);
-   kfree(to_priv(dev));
-   set_priv(dev, NULL);
-
return ret;
 }
 
 static void ipmmu_remove_device(struct device *dev)
 {
-   struct ipmmu_vmsa_iommu_priv *priv = to_priv(dev);
-
arm_iommu_detach_device(dev);
iommu_group_remove_device(dev);
-
-   kfree(priv->utlbs);
-   kfree(priv);
-
-   set_priv(dev, NULL);
 }
 
 static const struct iommu_ops ipmmu_ops = {
@@ -849,6 +844,7 @@ static const struct iommu_ops ipmmu_ops
.add_device = ipmmu_add_device,
.remove_device = ipmmu_remove_device,
.pgsize_bitmap = SZ_1G | SZ_2M | SZ_4K,
+   .of_xlate = ipmmu_of_xlate,
 };
 
 #endif /* !CONFIG_ARM && CONFIG_IOMMU_DMA */
@@ -958,19 +954,6 @@ static struct iommu_group *ipmmu_find_gr
return group;
 }
 
-static int ipmmu_of_xlate_dma(struct device *dev,
- struct of_phandle_args *spec)
-{
-   /* If the IPMMU device is disabled in DT then return error
-* to make sure the of_iommu code does not install ops
-* even though the iommu device is disabled
-*/
-   if (!of_device_is_available(spec->np))
-   return -ENODEV;
-
-   return ipmmu_init_platform_device(dev);
-}
-
 static const struct iommu_ops ipmmu_ops = {
.domain_alloc = ipmmu_domain_alloc_dma,
.domain_free = ipmmu_domain_free_dma,
@@ -984,7 +967,7 @@ static const struct iommu_ops ipmmu_ops
.remove_device = ipmmu_remove_device_dma,
.device_group = ipmmu_find_group_dma,
.pgsize_bitmap = SZ_1G | SZ_2M | SZ_4K,
-   .of_xlate = ipmmu_of_xlate_dma,
+   .of_xlate = ipmmu_of_xlate,
 };
 
 #endif /* CONFIG_IOMMU_DMA */


[PATCH v2 01/05] iommu/ipmmu-vmsa: Use iommu_device_register()/unregister()

2017-07-17 Thread Magnus Damm
From: Magnus Damm 

Extend the driver to make use of iommu_device_register()/unregister()
functions together with iommu_device_set_ops() and iommu_set_fwnode().

These used to be part of the earlier posted 64-bit ARM (r8a7795) series but
it turns out that these days they are required on 32-bit ARM as well.

Signed-off-by: Magnus Damm 
---

 Changes since V1:
 - Perform iommu_device_set_ops() and iommu_device_set_fwnode() before
   iommu_device_register() - thanks Robin!

 drivers/iommu/ipmmu-vmsa.c |   10 ++
 1 file changed, 10 insertions(+)

--- 0001/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-07-17 21:01:47.140607110 +0900
@@ -35,6 +35,7 @@
 struct ipmmu_vmsa_device {
struct device *dev;
void __iomem *base;
+   struct iommu_device iommu;
struct list_head list;
 
unsigned int num_utlbs;
@@ -1054,6 +1055,13 @@ static int ipmmu_probe(struct platform_d
 
ipmmu_device_reset(mmu);
 
+   iommu_device_set_ops(&mmu->iommu, &ipmmu_ops);
+   iommu_device_set_fwnode(&mmu->iommu, &pdev->dev.of_node->fwnode);
+
+   ret = iommu_device_register(&mmu->iommu);
+   if (ret)
+   return ret;
+
/*
 * We can't create the ARM mapping here as it requires the bus to have
 * an IOMMU, which only happens when bus_set_iommu() is called in
@@ -1077,6 +1085,8 @@ static int ipmmu_remove(struct platform_
list_del(&mmu->list);
spin_unlock(&ipmmu_devices_lock);
 
+   iommu_device_unregister(&mmu->iommu);
+
 #if defined(CONFIG_ARM) && !defined(CONFIG_IOMMU_DMA)
arm_iommu_release_mapping(mmu->mapping);
 #endif


[PATCH v2 00/05] iommu/ipmmu-vmsa: 32-bit ARM update V2

2017-07-17 Thread Magnus Damm
iommu/ipmmu-vmsa: 32-bit ARM update V2

[PATCH v2 01/05] iommu/ipmmu-vmsa: Use iommu_device_register()/unregister()
[PATCH v2 02/05] iommu/ipmmu-vmsa: Consistent ->of_xlate() handling
[PATCH v2 03/05] iommu/ipmmu-vmsa: Use fwspec on both 32 and 64-bit ARM
[PATCH v2 04/05] iommu/ipmmu-vmsa: Replace local utlb code with fwspec ids
[PATCH v2 05/05] iommu/ipmmu-vmsa: Clean up device tracking

This series updates the IPMMU driver to make use of recent IOMMU framework
changes and also improves code sharing in the driver between the 32-bit and
64-bit dma-mapping architecture glue code.

Suggested-by: Robin Murphy  (Patch 2 and 4)
Signed-off-by: Robin Murphy  (Patch 3 and 5)
Signed-off-by: Magnus Damm 
---

 Changes since V1:
 - Minor changes to patch 1 and 2 - thanks Robin and Geert!
 - Added patch 5 to include further clean ups

 Developed on top of v4.13-rc1

 drivers/iommu/ipmmu-vmsa.c |  198 ++--
 1 file changed, 49 insertions(+), 149 deletions(-)


[PATCH v4 1/3] iommu/ipmmu-vmsa: Add r8a7796 DT binding

2017-06-19 Thread Magnus Damm
From: Magnus Damm 

Update the IPMMU DT binding documentation to include the r8a7796 compat
string for R-Car M3-W.

Signed-off-by: Magnus Damm 
Acked-by: Laurent Pinchart 
Acked-by: Rob Herring 
Acked-by: Simon Horman 
Acked-by: Geert Uytterhoeven 
---

 Changes since V3:
 - None

 Changes since V2:
 - None

 Changes since V1:
 - Included in series, added Acked-by from Geert - thanks!

 Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt |1 +
 1 file changed, 1 insertion(+)

--- 0001/Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt
+++ work/Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt 
2017-06-19 19:51:13.990607110 +0900
@@ -16,6 +16,7 @@ Required Properties:
 - "renesas,ipmmu-r8a7793" for the R8A7793 (R-Car M2-N) IPMMU.
 - "renesas,ipmmu-r8a7794" for the R8A7794 (R-Car E2) IPMMU.
 - "renesas,ipmmu-r8a7795" for the R8A7795 (R-Car H3) IPMMU.
+- "renesas,ipmmu-r8a7796" for the R8A7796 (R-Car M3-W) IPMMU.
 - "renesas,ipmmu-vmsa" for generic R-Car Gen2 VMSA-compatible IPMMU.
 
   - reg: Base address and size of the IPMMU registers.


[PATCH v4 3/3] iommu/ipmmu-vmsa: Hook up r8a7796 DT matching code

2017-06-19 Thread Magnus Damm
From: Magnus Damm 

Support the r8a7796 IPMMU by sharing feature flags between
r8a7795 and r8a7796. Also update IOMMU_OF_DECLARE to hook
up the updated compat string.

Signed-off-by: Magnus Damm 
Reviewed-by: Geert Uytterhoeven 
---

 Changes since V3:
 - Added Reviewed-by from Geert - thanks!

 Changes since V2:
 - Updated to include white list suppport

 Changes since V1:
 - None

 drivers/iommu/ipmmu-vmsa.c |   14 ++
 1 file changed, 10 insertions(+), 4 deletions(-)

--- 0016/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-06-19 19:48:27.430607110 +0900
@@ -755,8 +755,9 @@ static bool ipmmu_slave_whitelist(struct
return false;
 }
 
-static const struct soc_device_attribute soc_r8a7795[] = {
+static const struct soc_device_attribute soc_rcar_gen3[] = {
{ .soc_id = "r8a7795", },
+   { .soc_id = "r8a7796", },
{ /* sentinel */ }
 };
 
@@ -772,7 +773,7 @@ static int ipmmu_of_xlate(struct device
}
 
/* For R-Car Gen3 use a white list to opt-in slave devices */
-   if (soc_device_match(soc_r8a7795) && !ipmmu_slave_whitelist(dev))
+   if (soc_device_match(soc_rcar_gen3) && !ipmmu_slave_whitelist(dev))
return -ENODEV;
 
iommu_fwspec_add_ids(dev, spec->args, 1);
@@ -1034,7 +1035,7 @@ static const struct ipmmu_features ipmmu
.twobit_imttbcr_sl0 = false,
 };
 
-static const struct ipmmu_features ipmmu_features_r8a7795 = {
+static const struct ipmmu_features ipmmu_features_rcar_gen3 = {
.use_ns_alias_offset = false,
.has_cache_leaf_nodes = true,
.number_of_contexts = 8,
@@ -1048,7 +1049,10 @@ static const struct of_device_id ipmmu_o
.data = &ipmmu_features_default,
}, {
.compatible = "renesas,ipmmu-r8a7795",
-   .data = &ipmmu_features_r8a7795,
+   .data = &ipmmu_features_rcar_gen3,
+   }, {
+   .compatible = "renesas,ipmmu-r8a7796",
+   .data = &ipmmu_features_rcar_gen3,
}, {
/* Terminator */
},
@@ -1229,6 +1233,8 @@ IOMMU_OF_DECLARE(ipmmu_vmsa_iommu_of, "r
 ipmmu_vmsa_iommu_of_setup);
 IOMMU_OF_DECLARE(ipmmu_r8a7795_iommu_of, "renesas,ipmmu-r8a7795",
 ipmmu_vmsa_iommu_of_setup);
+IOMMU_OF_DECLARE(ipmmu_r8a7796_iommu_of, "renesas,ipmmu-r8a7796",
+ipmmu_vmsa_iommu_of_setup);
 #endif
 
 MODULE_DESCRIPTION("IOMMU API for Renesas VMSA-compatible IPMMU");


[PATCH v4 2/3] iommu/ipmmu-vmsa: Increase maximum micro-TLBS to 48

2017-06-19 Thread Magnus Damm
From: Magnus Damm 

Bump up the maximum numbers of micro-TLBS to 48.

Each IPMMU device instance get micro-TLB assignment via
the "iommus" property in DT. Older SoCs tend to use a
maximum number of 32 micro-TLBs per IPMMU instance however
newer SoCs such as r8a7796 make use of up to 48 micro-TLBs.

At this point no SoC specific handling is done to validate
the maximum number of micro-TLBs, and because of that the
DT information is assumed to be within correct range for
each particular SoC.

If needed in the future SoC specific feature flags can be
added to handle the maximum number of micro-TLBs without
requiring DT changes, however at this point this does not
seem necessary.

Signed-off-by: Magnus Damm 
Reviewed-by: Geert Uytterhoeven 
---

 Changes since V3:
 - None

 Changes since V2:
 - Added outer set of () to IMUASID() and IMUCTR() - thanks Ramesh!
 - Added Reviewed-by from Geert - thanks!

 Changes since V1:
 - Added support for the second I/O range at 0x600.

 drivers/iommu/ipmmu-vmsa.c |   10 +++---
 1 file changed, 7 insertions(+), 3 deletions(-)

--- 0015/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-06-19 19:47:28.950607110 +0900
@@ -199,7 +199,9 @@ static struct ipmmu_vmsa_iommu_priv *to_
 #define IMPMBA(n)  (0x0280 + ((n) * 4))
 #define IMPMBD(n)  (0x02c0 + ((n) * 4))
 
-#define IMUCTR(n)  (0x0300 + ((n) * 16))
+#define IMUCTR(n)  ((n) < 32 ? IMUCTR0(n) : IMUCTR32(n))
+#define IMUCTR0(n) (0x0300 + ((n) * 16))
+#define IMUCTR32(n)(0x0600 + (((n) - 32) * 16))
 #define IMUCTR_FIXADDEN(1 << 31)
 #define IMUCTR_FIXADD_MASK (0xff << 16)
 #define IMUCTR_FIXADD_SHIFT16
@@ -209,7 +211,9 @@ static struct ipmmu_vmsa_iommu_priv *to_
 #define IMUCTR_FLUSH   (1 << 1)
 #define IMUCTR_MMUEN   (1 << 0)
 
-#define IMUASID(n) (0x0308 + ((n) * 16))
+#define IMUASID(n) ((n) < 32 ? IMUASID0(n) : IMUASID32(n))
+#define IMUASID0(n)(0x0308 + ((n) * 16))
+#define IMUASID32(n)   (0x0608 + (((n) - 32) * 16))
 #define IMUASID_ASID8_MASK (0xff << 8)
 #define IMUASID_ASID8_SHIFT8
 #define IMUASID_ASID0_MASK (0xff << 0)
@@ -1066,7 +1070,7 @@ static int ipmmu_probe(struct platform_d
}
 
mmu->dev = &pdev->dev;
-   mmu->num_utlbs = 32;
+   mmu->num_utlbs = 48;
spin_lock_init(&mmu->lock);
bitmap_zero(mmu->ctx, IPMMU_CTX_MAX);
mmu->features = of_device_get_match_data(&pdev->dev);


[PATCH v4 0/3] iommu/ipmmu-vmsa: r8a7796 support V4

2017-06-19 Thread Magnus Damm
iommu/ipmmu-vmsa: r8a7796 support V4

[PATCH v4 1/3] iommu/ipmmu-vmsa: Add r8a7796 DT binding
[PATCH v4 2/3] iommu/ipmmu-vmsa: Increase maximum micro-TLBS to 48
[PATCH v4 3/3] iommu/ipmmu-vmsa: Hook up r8a7796 DT matching code

This series adds r8a7796 support to the IPMMU driver. The DT binding
gets updated, maximum number of micro-TLBs are increased and the
driver is adjusted to match on the new DT binding.

Changes since V3:
 - Rebased on top of [PATCH v4 00/09] iommu/ipmmu-vmsa: r8a7795 support V4
 - Patch 3/3 updated with Reviewed-by - thanks Geert!

Changes since V2:
 - Patch 2/3 updated with an outer set of () - thanks Ramesh!
 - Patch 2/3 updated with Reviewed-by - thanks Geert!
 - Patch 3/3 updated to include white list support

Changes since V1:
 - Patch 1/3 updated with more Acked-by tags
 - Patch 2/3 updated with high I/O register range support

Patch 1/3 is ready for upstream merge and includes the following tags:
Signed-off-by: Magnus Damm 
Acked-by: Laurent Pinchart 
Acked-by: Rob Herring 
Acked-by: Simon Horman 
Acked-by: Geert Uytterhoeven 

Patch 2/3 and 3/3 are quite trivial but have no acked-by so far.

Signed-off-by: Magnus Damm 
---

 Developed on top of next-20170614 with the following series applied
 [PATCH 00/04] iommu/ipmmu-vmsa: 32-bit ARM update
 [PATCH v4 00/09] iommu/ipmmu-vmsa: r8a7795 support V4

 Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt |1 
 drivers/iommu/ipmmu-vmsa.c |   24 
+++---
 2 files changed, 18 insertions(+), 7 deletions(-)


[PATCH v4 09/09] iommu/ipmmu-vmsa: Hook up r8a7795 DT matching code

2017-06-19 Thread Magnus Damm
From: Magnus Damm 

Tie in r8a7795 features and update the IOMMU_OF_DECLARE
compat string to include the updated compat string.

Signed-off-by: Magnus Damm 
---

 Changes since V3:
 - Rebased code on top of
   [PATCH 00/04] iommu/ipmmu-vmsa: 32-bit ARM update
   This includes support for iommu_fwspec_add_ids()
 - Use dev_err() instead of dev_info() - Thanks Geert!
 - Moved single-invokation check into of_xlate() - Thanks Geert!
 - Dropped TODO list
 
 Changes since V2:
 - Check for lack of root device in ->xlate()
   This fixed a bug when IPMMU-MM is disabled in DT the system hangs on boot
 - Added code to ipmmu_init_platform_device() to handle multiple ->xlate() calls
 - Include empty white list by default
 - Updated TODO list

 Changes since V1:
 - Enable multi context feature
 - Update TODO list

 drivers/iommu/ipmmu-vmsa.c |   48 
 1 file changed, 44 insertions(+), 4 deletions(-)

--- 0029/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-06-19 14:10:58.930607110 +0900
@@ -25,6 +25,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #if defined(CONFIG_ARM) && !defined(CONFIG_IOMMU_DMA)
 #include 
@@ -730,10 +731,6 @@ static int ipmmu_init_platform_device(st
struct platform_device *ipmmu_pdev;
struct ipmmu_vmsa_iommu_priv *priv;
 
-   /* Initialize once - xlate() will call multiple times */
-   if (to_priv(dev))
-   return 0;
-
ipmmu_pdev = of_find_device_by_node(args->np);
if (!ipmmu_pdev)
return -ENODEV;
@@ -748,11 +745,41 @@ static int ipmmu_init_platform_device(st
return 0;
 }
 
+static bool ipmmu_slave_whitelist(struct device *dev)
+{
+   /* By default, do not allow use of IPMMU */
+   return false;
+}
+
+static const struct soc_device_attribute soc_r8a7795[] = {
+   { .soc_id = "r8a7795", },
+   { /* sentinel */ }
+};
+
 static int ipmmu_of_xlate(struct device *dev,
  struct of_phandle_args *spec)
 {
+   /* Failing in ->attach_device() results in a hang, so make
+* sure the root device is installed before going there
+*/
+   if (!__ipmmu_find_root()) {
+   dev_err(dev, "Unable to locate IPMMU root device\n");
+   return -ENODEV;
+   }
+
+   /* For R-Car Gen3 use a white list to opt-in slave devices */
+   if (soc_device_match(soc_r8a7795) && !ipmmu_slave_whitelist(dev))
+   return -ENODEV;
+
iommu_fwspec_add_ids(dev, spec->args, 1);
 
+   /*
+* Execute ipmmu_init_platform_device() once per device.
+* This xlate() callback will be invoked multiple times.
+*/
+   if (to_priv(dev))
+   return 0;
+
return ipmmu_init_platform_device(dev, spec);
 }
 
@@ -1003,11 +1030,22 @@ static const struct ipmmu_features ipmmu
.twobit_imttbcr_sl0 = false,
 };
 
+static const struct ipmmu_features ipmmu_features_r8a7795 = {
+   .use_ns_alias_offset = false,
+   .has_cache_leaf_nodes = true,
+   .number_of_contexts = 8,
+   .setup_imbuscr = false,
+   .twobit_imttbcr_sl0 = true,
+};
+
 static const struct of_device_id ipmmu_of_ids[] = {
{
.compatible = "renesas,ipmmu-vmsa",
.data = &ipmmu_features_default,
}, {
+   .compatible = "renesas,ipmmu-r8a7795",
+   .data = &ipmmu_features_r8a7795,
+   }, {
/* Terminator */
},
 };
@@ -1185,6 +1223,8 @@ static int __init ipmmu_vmsa_iommu_of_se
 
 IOMMU_OF_DECLARE(ipmmu_vmsa_iommu_of, "renesas,ipmmu-vmsa",
 ipmmu_vmsa_iommu_of_setup);
+IOMMU_OF_DECLARE(ipmmu_r8a7795_iommu_of, "renesas,ipmmu-r8a7795",
+ipmmu_vmsa_iommu_of_setup);
 #endif
 
 MODULE_DESCRIPTION("IOMMU API for Renesas VMSA-compatible IPMMU");


[PATCH v4 04/09] iommu/ipmmu-vmsa: Make use of IOMMU_OF_DECLARE()

2017-06-19 Thread Magnus Damm
From: Magnus Damm 

Hook up IOMMU_OF_DECLARE() support in case CONFIG_IOMMU_DMA
is enabled. The only current supported case for 32-bit ARM
is disabled, however for 64-bit ARM usage of OF is required.

Signed-off-by: Magnus Damm 
---

 Changes since V3:
 - Reworked to fit on top of
   [PATCH 00/04] iommu/ipmmu-vmsa: 32-bit ARM update

 Changes since V2:
 - Reworked registration code to make use of recently introduced:
 iommu_device_register()
 iommu_device_set_ops()
 iommu_device_set_fwnode()

 Changes since V1:
 - Reworked slightly to fit updated patch order and
   [PATCH v3 00/06] iommu/ipmmu-vmsa: IPMMU multi-arch update V3

 drivers/iommu/ipmmu-vmsa.c |   43 +--
 1 file changed, 37 insertions(+), 6 deletions(-)

--- 0019/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-06-19 14:03:53.140607110 +0900
@@ -20,6 +20,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -1055,13 +1056,25 @@ static int ipmmu_probe(struct platform_d
ipmmu_device_reset(mmu);
}
 
-   ret = iommu_device_register(&mmu->iommu);
-   if (ret)
-   return ret;
-
-   iommu_device_set_ops(&mmu->iommu, &ipmmu_ops);
-   iommu_device_set_fwnode(&mmu->iommu, &pdev->dev.of_node->fwnode);
+   /*
+* Register the IPMMU to the IOMMU subsystem in the following cases:
+* - R-Car Gen2 IPMMU (all devices registered)
+* - R-Car Gen3 IPMMU (leaf devices only - skip root IPMMU-MM device)
+*/
+   if (!mmu->features->has_cache_leaf_nodes || mmu->is_leaf) {
+   ret = iommu_device_register(&mmu->iommu);
+   if (ret)
+   return ret;
 
+   iommu_device_set_ops(&mmu->iommu, &ipmmu_ops);
+   iommu_device_set_fwnode(&mmu->iommu,
+   &pdev->dev.of_node->fwnode);
+
+#if defined(CONFIG_IOMMU_DMA)
+   if (!iommu_present(&platform_bus_type))
+   bus_set_iommu(&platform_bus_type, &ipmmu_ops);
+#endif
+   }
/*
 * We can't create the ARM mapping here as it requires the bus to have
 * an IOMMU, which only happens when bus_set_iommu() is called in
@@ -1107,15 +1120,22 @@ static struct platform_driver ipmmu_driv
 
 static int __init ipmmu_init(void)
 {
+   static bool setup_done;
int ret;
 
+   if (setup_done)
+   return 0;
+
ret = platform_driver_register(&ipmmu_driver);
if (ret < 0)
return ret;
 
+#if defined(CONFIG_ARM) && !defined(CONFIG_IOMMU_DMA)
if (!iommu_present(&platform_bus_type))
bus_set_iommu(&platform_bus_type, &ipmmu_ops);
+#endif
 
+   setup_done = true;
return 0;
 }
 
@@ -1127,6 +1147,17 @@ static void __exit ipmmu_exit(void)
 subsys_initcall(ipmmu_init);
 module_exit(ipmmu_exit);
 
+#ifdef CONFIG_IOMMU_DMA
+static int __init ipmmu_vmsa_iommu_of_setup(struct device_node *np)
+{
+   ipmmu_init();
+   return 0;
+}
+
+IOMMU_OF_DECLARE(ipmmu_vmsa_iommu_of, "renesas,ipmmu-vmsa",
+ipmmu_vmsa_iommu_of_setup);
+#endif
+
 MODULE_DESCRIPTION("IOMMU API for Renesas VMSA-compatible IPMMU");
 MODULE_AUTHOR("Laurent Pinchart ");
 MODULE_LICENSE("GPL v2");


[PATCH v4 08/09] iommu/ipmmu-vmsa: Allow two bit SL0

2017-06-19 Thread Magnus Damm
From: Magnus Damm 

Introduce support for two bit SL0 bitfield in IMTTBCR
by using a separate feature flag.

Signed-off-by: Magnus Damm 
---

 Changes since V3:
 - None

 Changes since V2:
 - None

 Changes since V1:
 - None

 drivers/iommu/ipmmu-vmsa.c |   14 +-
 1 file changed, 13 insertions(+), 1 deletion(-)

--- 0027/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-06-19 14:08:26.100607110 +0900
@@ -40,6 +40,7 @@ struct ipmmu_features {
bool has_cache_leaf_nodes;
unsigned int number_of_contexts;
bool setup_imbuscr;
+   bool twobit_imttbcr_sl0;
 };
 
 struct ipmmu_vmsa_device {
@@ -149,6 +150,10 @@ static struct ipmmu_vmsa_iommu_priv *to_
 #define IMTTBCR_TSZ0_MASK  (7 << 0)
 #define IMTTBCR_TSZ0_SHIFT O
 
+#define IMTTBCR_SL0_TWOBIT_LVL_3   (0 << 6)
+#define IMTTBCR_SL0_TWOBIT_LVL_2   (1 << 6)
+#define IMTTBCR_SL0_TWOBIT_LVL_1   (2 << 6)
+
 #define IMBUSCR0x000c
 #define IMBUSCR_DVM(1 << 2)
 #define IMBUSCR_BUSSEL_SYS (0 << 0)
@@ -393,6 +398,7 @@ static int ipmmu_domain_allocate_context
 static int ipmmu_domain_init_context(struct ipmmu_vmsa_domain *domain)
 {
u64 ttbr;
+   u32 tmp;
int ret;
 
/*
@@ -445,9 +451,14 @@ static int ipmmu_domain_init_context(str
 * We use long descriptors with inner-shareable WBWA tables and allocate
 * the whole 32-bit VA space to TTBR0.
 */
+   if (domain->root->features->twobit_imttbcr_sl0)
+   tmp = IMTTBCR_SL0_TWOBIT_LVL_1;
+   else
+   tmp = IMTTBCR_SL0_LVL_1;
+
ipmmu_ctx_write_root(domain, IMTTBCR, IMTTBCR_EAE |
 IMTTBCR_SH0_INNER_SHAREABLE | IMTTBCR_ORGN0_WB_WA |
-IMTTBCR_IRGN0_WB_WA | IMTTBCR_SL0_LVL_1);
+IMTTBCR_IRGN0_WB_WA | tmp);
 
/* MAIR0 */
ipmmu_ctx_write_root(domain, IMMAIR0,
@@ -989,6 +1000,7 @@ static const struct ipmmu_features ipmmu
.has_cache_leaf_nodes = false,
.number_of_contexts = 1, /* software only tested with one context */
.setup_imbuscr = true,
+   .twobit_imttbcr_sl0 = false,
 };
 
 static const struct of_device_id ipmmu_of_ids[] = {


[PATCH v4 07/09] iommu/ipmmu-vmsa: Make IMBUSCTR setup optional

2017-06-19 Thread Magnus Damm
From: Magnus Damm 

Introduce a feature to allow opt-out of setting up
IMBUSCR. The default case is unchanged.

Signed-off-by: Magnus Damm 
---

 Changes since V3:
 - None

 Changes since V2:
 - None

 Changes since V1:
 - Updated the commit message
 - Reworked patch to coexist with the multi context feature

 drivers/iommu/ipmmu-vmsa.c |9 ++---
 1 file changed, 6 insertions(+), 3 deletions(-)

--- 0025/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-06-19 14:07:06.850607110 +0900
@@ -39,6 +39,7 @@ struct ipmmu_features {
bool use_ns_alias_offset;
bool has_cache_leaf_nodes;
unsigned int number_of_contexts;
+   bool setup_imbuscr;
 };
 
 struct ipmmu_vmsa_device {
@@ -453,9 +454,10 @@ static int ipmmu_domain_init_context(str
 domain->cfg.arm_lpae_s1_cfg.mair[0]);
 
/* IMBUSCR */
-   ipmmu_ctx_write_root(domain, IMBUSCR,
-ipmmu_ctx_read_root(domain, IMBUSCR) &
-~(IMBUSCR_DVM | IMBUSCR_BUSSEL_MASK));
+   if (domain->root->features->setup_imbuscr)
+   ipmmu_ctx_write_root(domain, IMBUSCR,
+ipmmu_ctx_read_root(domain, IMBUSCR) &
+~(IMBUSCR_DVM | IMBUSCR_BUSSEL_MASK));
 
/*
 * IMSTR
@@ -986,6 +988,7 @@ static const struct ipmmu_features ipmmu
.use_ns_alias_offset = true,
.has_cache_leaf_nodes = false,
.number_of_contexts = 1, /* software only tested with one context */
+   .setup_imbuscr = true,
 };
 
 static const struct of_device_id ipmmu_of_ids[] = {


[PATCH v4 05/09] iommu/ipmmu-vmsa: IPMMU device is 40-bit bus master

2017-06-19 Thread Magnus Damm
From: Magnus Damm 

The r8a7795 IPMMU supports 40-bit bus mastering. Both
the coherent DMA mask and the streaming DMA mask are
set to unlock the 40-bit address space for coherent
allocations and streaming operations.

Signed-off-by: Magnus Damm 
---

 Changes since V3:
 - None

 Changes since V2:
 - Updated the code and commit message to use 40 bits instead of 64 bits

 Changes since V1:
 - Updated the commit message

 drivers/iommu/ipmmu-vmsa.c |1 +
 1 file changed, 1 insertion(+)

--- 0021/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-06-19 14:05:33.720607110 +0900
@@ -1004,6 +1004,7 @@ static int ipmmu_probe(struct platform_d
spin_lock_init(&mmu->lock);
bitmap_zero(mmu->ctx, IPMMU_CTX_MAX);
mmu->features = of_device_get_match_data(&pdev->dev);
+   dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(40));
 
/* Map I/O memory and request IRQ. */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);


[PATCH v4 06/09] iommu/ipmmu-vmsa: Write IMCTR twice

2017-06-19 Thread Magnus Damm
From: Magnus Damm 

Write IMCTR both in the root device and the leaf node.

To allow access of IMCTR introduce the following function:
 - ipmmu_ctx_write_all()

While at it also rename context functions:
 - ipmmu_ctx_read() -> ipmmu_ctx_read_root()
 - ipmmu_ctx_write() -> ipmmu_ctx_write_root()

Signed-off-by: Magnus Damm 
---

 Changes since V3:
 - Changed function names to improve code readability - Thanks Robin!

 Changes since V2:
 - None

 Changes since V1:
 - None

 drivers/iommu/ipmmu-vmsa.c |   55 +++-
 1 file changed, 34 insertions(+), 21 deletions(-)

--- 0023/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-06-19 14:06:16.770607110 +0900
@@ -261,17 +261,28 @@ static void ipmmu_write(struct ipmmu_vms
iowrite32(data, mmu->base + offset);
 }
 
-static u32 ipmmu_ctx_read(struct ipmmu_vmsa_domain *domain, unsigned int reg)
+static u32 ipmmu_ctx_read_root(struct ipmmu_vmsa_domain *domain,
+  unsigned int reg)
 {
return ipmmu_read(domain->root, domain->context_id * IM_CTX_SIZE + reg);
 }
 
-static void ipmmu_ctx_write(struct ipmmu_vmsa_domain *domain, unsigned int reg,
-   u32 data)
+static void ipmmu_ctx_write_root(struct ipmmu_vmsa_domain *domain,
+unsigned int reg, u32 data)
 {
ipmmu_write(domain->root, domain->context_id * IM_CTX_SIZE + reg, data);
 }
 
+static void ipmmu_ctx_write_all(struct ipmmu_vmsa_domain *domain,
+   unsigned int reg, u32 data)
+{
+   if (domain->mmu != domain->root)
+   ipmmu_write(domain->mmu,
+   domain->context_id * IM_CTX_SIZE + reg, data);
+
+   ipmmu_write(domain->root, domain->context_id * IM_CTX_SIZE + reg, data);
+}
+
 /* 
-
  * TLB and microTLB Management
  */
@@ -281,7 +292,7 @@ static void ipmmu_tlb_sync(struct ipmmu_
 {
unsigned int count = 0;
 
-   while (ipmmu_ctx_read(domain, IMCTR) & IMCTR_FLUSH) {
+   while (ipmmu_ctx_read_root(domain, IMCTR) & IMCTR_FLUSH) {
cpu_relax();
if (++count == TLB_LOOP_TIMEOUT) {
dev_err_ratelimited(domain->mmu->dev,
@@ -296,9 +307,9 @@ static void ipmmu_tlb_invalidate(struct
 {
u32 reg;
 
-   reg = ipmmu_ctx_read(domain, IMCTR);
+   reg = ipmmu_ctx_read_root(domain, IMCTR);
reg |= IMCTR_FLUSH;
-   ipmmu_ctx_write(domain, IMCTR, reg);
+   ipmmu_ctx_write_all(domain, IMCTR, reg);
 
ipmmu_tlb_sync(domain);
 }
@@ -425,31 +436,32 @@ static int ipmmu_domain_init_context(str
 
/* TTBR0 */
ttbr = domain->cfg.arm_lpae_s1_cfg.ttbr[0];
-   ipmmu_ctx_write(domain, IMTTLBR0, ttbr);
-   ipmmu_ctx_write(domain, IMTTUBR0, ttbr >> 32);
+   ipmmu_ctx_write_root(domain, IMTTLBR0, ttbr);
+   ipmmu_ctx_write_root(domain, IMTTUBR0, ttbr >> 32);
 
/*
 * TTBCR
 * We use long descriptors with inner-shareable WBWA tables and allocate
 * the whole 32-bit VA space to TTBR0.
 */
-   ipmmu_ctx_write(domain, IMTTBCR, IMTTBCR_EAE |
-   IMTTBCR_SH0_INNER_SHAREABLE | IMTTBCR_ORGN0_WB_WA |
-   IMTTBCR_IRGN0_WB_WA | IMTTBCR_SL0_LVL_1);
+   ipmmu_ctx_write_root(domain, IMTTBCR, IMTTBCR_EAE |
+IMTTBCR_SH0_INNER_SHAREABLE | IMTTBCR_ORGN0_WB_WA |
+IMTTBCR_IRGN0_WB_WA | IMTTBCR_SL0_LVL_1);
 
/* MAIR0 */
-   ipmmu_ctx_write(domain, IMMAIR0, domain->cfg.arm_lpae_s1_cfg.mair[0]);
+   ipmmu_ctx_write_root(domain, IMMAIR0,
+domain->cfg.arm_lpae_s1_cfg.mair[0]);
 
/* IMBUSCR */
-   ipmmu_ctx_write(domain, IMBUSCR,
-   ipmmu_ctx_read(domain, IMBUSCR) &
-   ~(IMBUSCR_DVM | IMBUSCR_BUSSEL_MASK));
+   ipmmu_ctx_write_root(domain, IMBUSCR,
+ipmmu_ctx_read_root(domain, IMBUSCR) &
+~(IMBUSCR_DVM | IMBUSCR_BUSSEL_MASK));
 
/*
 * IMSTR
 * Clear all interrupt flags.
 */
-   ipmmu_ctx_write(domain, IMSTR, ipmmu_ctx_read(domain, IMSTR));
+   ipmmu_ctx_write_root(domain, IMSTR, ipmmu_ctx_read_root(domain, IMSTR));
 
/*
 * IMCTR
@@ -458,7 +470,8 @@ static int ipmmu_domain_init_context(str
 * software management as we have no use for it. Flush the TLB as
 * required when modifying the context registers.
 */
-   ipmmu_ctx_write(domain, IMCTR, IMCTR_INTEN | IMCTR_FLUSH | IMCTR_MMUEN);
+   ipmmu_ctx_write_all(domain, IMCTR,
+   IMCTR_INTEN | IMCTR_FLUSH | IMCTR_MMUEN);
 
return 0;
 }
@@ -484,7 +497,7 @@ static void i

[PATCH v4 03/09] iommu/ipmmu-vmsa: Enable multi context support

2017-06-19 Thread Magnus Damm
From: Magnus Damm 

Add support for up to 8 contexts. Each context is mapped to one
domain. One domain is assigned one or more slave devices. Contexts
are allocated dynamically and slave devices are grouped together
based on which IPMMU device they are connected to. This makes slave
devices tied to the same IPMMU device share the same IOVA space.

Signed-off-by: Magnus Damm 
---

 Changes since V3:
 - Use number_of_contexts unsigned int, drop WARN_ON() - Thanks Robin!

 Changes since V2:
 - Updated patch description to reflect code included in:
   [PATCH v7 00/07] iommu/ipmmu-vmsa: IPMMU multi-arch update V7

 Changes since V1:
 - Support up to 8 contexts instead of 4
 - Use feature flag and runtime handling
 - Default to single context

 drivers/iommu/ipmmu-vmsa.c |   31 +++
 1 file changed, 23 insertions(+), 8 deletions(-)

--- 0017/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-06-19 14:00:59.880607110 +0900
@@ -32,11 +32,12 @@
 
 #include "io-pgtable.h"
 
-#define IPMMU_CTX_MAX 1
+#define IPMMU_CTX_MAX 8
 
 struct ipmmu_features {
bool use_ns_alias_offset;
bool has_cache_leaf_nodes;
+   unsigned int number_of_contexts;
 };
 
 struct ipmmu_vmsa_device {
@@ -47,6 +48,7 @@ struct ipmmu_vmsa_device {
const struct ipmmu_features *features;
bool is_leaf;
unsigned int num_utlbs;
+   unsigned int num_ctx;
spinlock_t lock;/* Protects ctx and domains[] */
DECLARE_BITMAP(ctx, IPMMU_CTX_MAX);
struct ipmmu_vmsa_domain *domains[IPMMU_CTX_MAX];
@@ -363,11 +365,12 @@ static int ipmmu_domain_allocate_context
 
spin_lock_irqsave(&mmu->lock, flags);
 
-   ret = find_first_zero_bit(mmu->ctx, IPMMU_CTX_MAX);
-   if (ret != IPMMU_CTX_MAX) {
+   ret = find_first_zero_bit(mmu->ctx, mmu->num_ctx);
+   if (ret != mmu->num_ctx) {
mmu->domains[ret] = domain;
set_bit(ret, mmu->ctx);
-   }
+   } else
+   ret = -EBUSY;
 
spin_unlock_irqrestore(&mmu->lock, flags);
 
@@ -412,9 +415,9 @@ static int ipmmu_domain_init_context(str
 * Find an unused context.
 */
ret = ipmmu_domain_allocate_context(domain->root, domain);
-   if (ret == IPMMU_CTX_MAX) {
+   if (ret < 0) {
free_io_pgtable_ops(domain->iop);
-   return -EBUSY;
+   return ret;
}
 
domain->context_id = ret;
@@ -549,7 +552,7 @@ static irqreturn_t ipmmu_irq(int irq, vo
/*
 * Check interrupts for all active contexts.
 */
-   for (i = 0; i < IPMMU_CTX_MAX; i++) {
+   for (i = 0; i < mmu->num_ctx; i++) {
if (!mmu->domains[i])
continue;
if (ipmmu_domain_irq(mmu->domains[i]) == IRQ_HANDLED)
@@ -620,6 +623,14 @@ static int ipmmu_attach_device(struct io
domain->mmu = mmu;
domain->root = root;
ret = ipmmu_domain_init_context(domain);
+   if (ret < 0) {
+   dev_err(dev, "Unable to initialize IPMMU context\n");
+   domain->mmu = NULL;
+   domain->root = NULL;
+   } else {
+   dev_info(dev, "Using IPMMU context %u\n",
+domain->context_id);
+   }
} else if (domain->mmu != mmu) {
/*
 * Something is wrong, we can't attach two devices using
@@ -953,13 +964,14 @@ static void ipmmu_device_reset(struct ip
unsigned int i;
 
/* Disable all contexts. */
-   for (i = 0; i < 4; ++i)
+   for (i = 0; i < mmu->num_ctx; ++i)
ipmmu_write(mmu, i * IM_CTX_SIZE + IMCTR, 0);
 }
 
 static const struct ipmmu_features ipmmu_features_default = {
.use_ns_alias_offset = true,
.has_cache_leaf_nodes = false,
+   .number_of_contexts = 1, /* software only tested with one context */
 };
 
 static const struct of_device_id ipmmu_of_ids[] = {
@@ -1013,6 +1025,9 @@ static int ipmmu_probe(struct platform_d
if (mmu->features->use_ns_alias_offset)
mmu->base += IM_NS_ALIAS_OFFSET;
 
+   mmu->num_ctx = min_t(unsigned int, IPMMU_CTX_MAX,
+mmu->features->number_of_contexts);
+
irq = platform_get_irq(pdev, 0);
 
/*


[PATCH v4 00/09] iommu/ipmmu-vmsa: r8a7795 support V4

2017-06-19 Thread Magnus Damm
iommu/ipmmu-vmsa: r8a7795 support V4

[PATCH v4 01/09] iommu/ipmmu-vmsa: Introduce features, break out alias
[PATCH v4 02/09] iommu/ipmmu-vmsa: Add optional root device feature
[PATCH v4 03/09] iommu/ipmmu-vmsa: Enable multi context support
[PATCH v4 04/09] iommu/ipmmu-vmsa: Make use of IOMMU_OF_DECLARE()
[PATCH v4 05/09] iommu/ipmmu-vmsa: IPMMU device is 40-bit bus master
[PATCH v4 06/09] iommu/ipmmu-vmsa: Write IMCTR twice
[PATCH v4 07/09] iommu/ipmmu-vmsa: Make IMBUSCTR setup optional
[PATCH v4 08/09] iommu/ipmmu-vmsa: Allow two bit SL0
[PATCH v4 09/09] iommu/ipmmu-vmsa: Hook up r8a7795 DT matching code

Here's an updated series for r8a7795 IPMMU support. The patches adjust
the code based on feedback from Geert and Robin together with a rebase
to include changes from the recently posted series:

[PATCH 00/04] iommu/ipmmu-vmsa: 32-bit ARM update

The DT binding for r8a7795 has been accepted for upstream merge
and this series implements support following such format:

d4e42e7 iommu/ipmmu-vmsa: Add r8a7795 DT binding

The r8a7795 IPMMU is almost register compatible with earlier devices
like r8a7790-r8a7794, however some bitfields have been shifted
slightly. On a grander scale topology has been added and interrupts
have been reworked. So now there are several "cache" IPMMU units
without interrupt that somehow communicate with IPMMU-MM that
is the only instance that supports interrupts. The code refers to
IPMMU-MM as a "root" device and the other ones as "leaf" nodes.

Changes since V3:
 - Rebased on top of [PATCH 00/04] iommu/ipmmu-vmsa: 32-bit ARM update
 - Patch 1/9 has been updated to use of_device_get_match_data(), thanks Robin!
 - Patch 2/9 has been reworked to make it easier to follow, thanks Geert!
 - Patch 3/9 now uses unsigned int for context counts - thanks Robin!
 - Patch 6/9 now includes function name changes - thanks Robin! 
 - Patch 9/9 now uses dev_err() instead of dev_info() - thanks Geert!

Changes since V2:
 - Patch 2/9 has been updated with a bug fix and to supply __ipmmu_find_root()
 - Patch 4/9 now makes use of iommu_device_* functions
 - Patch 5/9 sets the mask to 40 bits instead of 64 bits
 - Patch 9/9 implements white list handling via ->xlate() and fixes a bug

Signed-off-by: Magnus Damm 
---

 Developed on top of next-20170614 with the following series applied
 [PATCH 00/04] iommu/ipmmu-vmsa: 32-bit ARM update

 drivers/iommu/ipmmu-vmsa.c |  327 ++--
 1 file changed, 260 insertions(+), 67 deletions(-)


[PATCH v4 02/09] iommu/ipmmu-vmsa: Add optional root device feature

2017-06-19 Thread Magnus Damm
From: Magnus Damm 

Add root device handling to the IPMMU driver by allowing certain
DT compat strings to enable has_cache_leaf_nodes that in turn will
support both root devices with interrupts and leaf devices that
face the actual IPMMU consumer devices.

Signed-off-by: Magnus Damm 
---

 Changes since V3:
 - Reworked root finding code to make it easier to follow, thanks Geert!
 
 Changes since V2:
 - Fixed a bug in ipmmu_find_root() when only leaf devices are present
 - Broke out __ipmmu_find_root() to allow ->xlate() check for root devices

 Changes since V1:
 - Moved patch to earlier in the series
 - Updated code to work with recent changes in:
   [PATCH v3 00/06] iommu/ipmmu-vmsa: IPMMU multi-arch update V3

 drivers/iommu/ipmmu-vmsa.c |   95 
 1 file changed, 78 insertions(+), 17 deletions(-)

--- 0015/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-06-19 13:59:41.050607110 +0900
@@ -36,6 +36,7 @@
 
 struct ipmmu_features {
bool use_ns_alias_offset;
+   bool has_cache_leaf_nodes;
 };
 
 struct ipmmu_vmsa_device {
@@ -44,6 +45,7 @@ struct ipmmu_vmsa_device {
struct iommu_device iommu;
struct list_head list;
const struct ipmmu_features *features;
+   bool is_leaf;
unsigned int num_utlbs;
spinlock_t lock;/* Protects ctx and domains[] */
DECLARE_BITMAP(ctx, IPMMU_CTX_MAX);
@@ -54,6 +56,7 @@ struct ipmmu_vmsa_device {
 
 struct ipmmu_vmsa_domain {
struct ipmmu_vmsa_device *mmu;
+   struct ipmmu_vmsa_device *root;
struct iommu_domain io_domain;
 
struct io_pgtable_cfg cfg;
@@ -203,6 +206,44 @@ static struct ipmmu_vmsa_iommu_priv *to_
 #define IMUASID_ASID0_SHIFT0
 
 /* 
-
+ * Root device handling
+ */
+
+static bool ipmmu_is_root(struct ipmmu_vmsa_device *mmu)
+{
+   if (mmu->features->has_cache_leaf_nodes)
+   return mmu->is_leaf ? false : true;
+   else
+   return true; /* older IPMMU hardware treated as single root */
+}
+
+static struct ipmmu_vmsa_device *__ipmmu_find_root(void)
+{
+   struct ipmmu_vmsa_device *mmu;
+   struct ipmmu_vmsa_device *root = NULL;
+
+   spin_lock(&ipmmu_devices_lock);
+
+   list_for_each_entry(mmu, &ipmmu_devices, list) {
+   if (ipmmu_is_root(mmu)) {
+   root = mmu;
+   break;
+   }
+   }
+
+   spin_unlock(&ipmmu_devices_lock);
+   return root;
+}
+
+static struct ipmmu_vmsa_device *ipmmu_find_root(struct ipmmu_vmsa_device 
*leaf)
+{
+   if (ipmmu_is_root(leaf))
+   return leaf;
+   else
+   return __ipmmu_find_root();
+}
+
+/* 
-
  * Read/Write Access
  */
 
@@ -219,13 +260,13 @@ static void ipmmu_write(struct ipmmu_vms
 
 static u32 ipmmu_ctx_read(struct ipmmu_vmsa_domain *domain, unsigned int reg)
 {
-   return ipmmu_read(domain->mmu, domain->context_id * IM_CTX_SIZE + reg);
+   return ipmmu_read(domain->root, domain->context_id * IM_CTX_SIZE + reg);
 }
 
 static void ipmmu_ctx_write(struct ipmmu_vmsa_domain *domain, unsigned int reg,
u32 data)
 {
-   ipmmu_write(domain->mmu, domain->context_id * IM_CTX_SIZE + reg, data);
+   ipmmu_write(domain->root, domain->context_id * IM_CTX_SIZE + reg, data);
 }
 
 /* 
-
@@ -360,7 +401,7 @@ static int ipmmu_domain_init_context(str
 * TODO: Add support for coherent walk through CCI with DVM and remove
 * cache handling. For now, delegate it to the io-pgtable code.
 */
-   domain->cfg.iommu_dev = domain->mmu->dev;
+   domain->cfg.iommu_dev = domain->root->dev;
 
domain->iop = alloc_io_pgtable_ops(ARM_32_LPAE_S1, &domain->cfg,
   domain);
@@ -370,7 +411,7 @@ static int ipmmu_domain_init_context(str
/*
 * Find an unused context.
 */
-   ret = ipmmu_domain_allocate_context(domain->mmu, domain);
+   ret = ipmmu_domain_allocate_context(domain->root, domain);
if (ret == IPMMU_CTX_MAX) {
free_io_pgtable_ops(domain->iop);
return -EBUSY;
@@ -441,7 +482,7 @@ static void ipmmu_domain_destroy_context
 */
ipmmu_ctx_write(domain, IMCTR, IMCTR_FLUSH);
ipmmu_tlb_sync(domain);
-   ipmmu_domain_free_context(domain->mmu, domain->context_id);
+   ipmmu_domain_free_context(domain->root, domain->context_id);
 }
 
 /* 
-
@@ -555,7 +596,7 @@ static int ipmmu_attach_device(struct io
 {
   

[PATCH v4 01/09] iommu/ipmmu-vmsa: Introduce features, break out alias

2017-06-19 Thread Magnus Damm
From: Magnus Damm 

Introduce struct ipmmu_features to track various hardware
and software implementation changes inside the driver for
different kinds of IPMMU hardware. Add use_ns_alias_offset
as a first example of a feature to control if the secure
register bank offset should be used or not.

Signed-off-by: Magnus Damm 
---

 Changes since V3:
 - Use of_device_get_match_data(), thanks Robin!

 Changes since V2:
 - None

 Changes since V1:
 - Moved patch to front of the series

 drivers/iommu/ipmmu-vmsa.c |   31 ---
 1 file changed, 24 insertions(+), 7 deletions(-)

--- 0014/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-06-19 13:57:36.300607110 +0900
@@ -19,6 +19,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -33,12 +34,16 @@
 
 #define IPMMU_CTX_MAX 1
 
+struct ipmmu_features {
+   bool use_ns_alias_offset;
+};
+
 struct ipmmu_vmsa_device {
struct device *dev;
void __iomem *base;
struct iommu_device iommu;
struct list_head list;
-
+   const struct ipmmu_features *features;
unsigned int num_utlbs;
spinlock_t lock;/* Protects ctx and domains[] */
DECLARE_BITMAP(ctx, IPMMU_CTX_MAX);
@@ -904,6 +909,21 @@ static void ipmmu_device_reset(struct ip
ipmmu_write(mmu, i * IM_CTX_SIZE + IMCTR, 0);
 }
 
+static const struct ipmmu_features ipmmu_features_default = {
+   .use_ns_alias_offset = true,
+};
+
+static const struct of_device_id ipmmu_of_ids[] = {
+   {
+   .compatible = "renesas,ipmmu-vmsa",
+   .data = &ipmmu_features_default,
+   }, {
+   /* Terminator */
+   },
+};
+
+MODULE_DEVICE_TABLE(of, ipmmu_of_ids);
+
 static int ipmmu_probe(struct platform_device *pdev)
 {
struct ipmmu_vmsa_device *mmu;
@@ -921,6 +941,7 @@ static int ipmmu_probe(struct platform_d
mmu->num_utlbs = 32;
spin_lock_init(&mmu->lock);
bitmap_zero(mmu->ctx, IPMMU_CTX_MAX);
+   mmu->features = of_device_get_match_data(&pdev->dev);
 
/* Map I/O memory and request IRQ. */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -940,7 +961,8 @@ static int ipmmu_probe(struct platform_d
 * Offset the registers base unconditionally to point to the non-secure
 * alias space for now.
 */
-   mmu->base += IM_NS_ALIAS_OFFSET;
+   if (mmu->features->use_ns_alias_offset)
+   mmu->base += IM_NS_ALIAS_OFFSET;
 
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
@@ -998,11 +1020,6 @@ static int ipmmu_remove(struct platform_
return 0;
 }
 
-static const struct of_device_id ipmmu_of_ids[] = {
-   { .compatible = "renesas,ipmmu-vmsa", },
-   { }
-};
-
 static struct platform_driver ipmmu_driver = {
.driver = {
.name = "ipmmu-vmsa",


Re: [PATCH 04/04] iommu/ipmmu-vmsa: Replace local utlb code with fwspec ids

2017-06-16 Thread Magnus Damm
Hi Geert,

On Fri, Jun 16, 2017 at 4:18 PM, Geert Uytterhoeven
 wrote:
> Hi Magnus,
>
> On Thu, Jun 15, 2017 at 12:29 PM, Magnus Damm  wrote:
>> Now when both 32-bit and 64-bit code inside the driver is using
>> fwspec it is possible to replace the utlb handling with fwspec ids
>> that get populated from ->of_xlate().
>
> Thanks for your patch!

Thanks for the feedback!

>> --- 0013/drivers/iommu/ipmmu-vmsa.c
>> +++ work/drivers/iommu/ipmmu-vmsa.c 2017-06-15 18:32:27.580607110 +0900
>
>>  static int ipmmu_of_xlate(struct device *dev,
>>   struct of_phandle_args *spec)
>>  {
>> -   return ipmmu_init_platform_device(dev);
>> +   iommu_fwspec_add_ids(dev, spec->args, 1);
>
> Does it hurt if iommu_fwspec_add_ids() is called multiple times, as this is
> done before the "Initialize once - xlate() will call multiple times" check?

The function needs to be called several times to populate the ids, so
that the "initialize once" check happens later is intentional and
correct. Perhaps a bit unclear though...

>> +
>> +   return ipmmu_init_platform_device(dev, spec);
>>  }

Cheers,

/ magnus


[PATCH 02/04] iommu/ipmmu-vmsa: Consistent ->of_xlate() handling

2017-06-15 Thread Magnus Damm
From: Magnus Damm 

The 32-bit ARM code gets updated to make use of ->of_xlate() and the
code is shared between 64-bit and 32-bit ARM. The of_device_is_available()
check gets dropped since it is included in of_iommu_xlate().

Suggested-by: Robin Murphy 
Signed-off-by: Magnus Damm 
---

 drivers/iommu/ipmmu-vmsa.c |   51 ++--
 1 file changed, 17 insertions(+), 34 deletions(-)

--- 0009/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-06-15 17:22:27.460607110 +0900
@@ -680,6 +680,10 @@ static int ipmmu_init_platform_device(st
int num_utlbs;
int ret = -ENODEV;
 
+   /* Initialize once - xlate() will call multiple times */
+   if (to_priv(dev))
+   return 0;
+
/* Find the master corresponding to the device. */
 
num_utlbs = of_count_phandle_with_args(dev->of_node, "iommus",
@@ -734,6 +738,12 @@ error:
return ret;
 }
 
+static int ipmmu_of_xlate(struct device *dev,
+ struct of_phandle_args *spec)
+{
+   return ipmmu_init_platform_device(dev);
+}
+
 #if defined(CONFIG_ARM) && !defined(CONFIG_IOMMU_DMA)
 
 static struct iommu_domain *ipmmu_domain_alloc(unsigned type)
@@ -750,11 +760,11 @@ static int ipmmu_add_device(struct devic
struct iommu_group *group;
int ret;
 
-   if (to_priv(dev)) {
-   dev_warn(dev, "IOMMU driver already assigned to device %s\n",
-dev_name(dev));
-   return -EINVAL;
-   }
+   /*
+* Only let through devices that have been verified in xlate()
+*/
+   if (!to_priv(dev))
+   return -ENODEV;
 
/* Create a device group and add the device to it. */
group = iommu_group_alloc();
@@ -773,10 +783,6 @@ static int ipmmu_add_device(struct devic
goto error;
}
 
-   ret = ipmmu_init_platform_device(dev);
-   if (ret < 0)
-   goto error;
-
/*
 * Create the ARM mapping, used by the ARM DMA mapping core to allocate
 * VAs. This will allocate a corresponding IOMMU domain.
@@ -817,24 +823,13 @@ error:
if (!IS_ERR_OR_NULL(group))
iommu_group_remove_device(dev);
 
-   kfree(to_priv(dev)->utlbs);
-   kfree(to_priv(dev));
-   set_priv(dev, NULL);
-
return ret;
 }
 
 static void ipmmu_remove_device(struct device *dev)
 {
-   struct ipmmu_vmsa_iommu_priv *priv = to_priv(dev);
-
arm_iommu_detach_device(dev);
iommu_group_remove_device(dev);
-
-   kfree(priv->utlbs);
-   kfree(priv);
-
-   set_priv(dev, NULL);
 }
 
 static const struct iommu_ops ipmmu_ops = {
@@ -849,6 +844,7 @@ static const struct iommu_ops ipmmu_ops
.add_device = ipmmu_add_device,
.remove_device = ipmmu_remove_device,
.pgsize_bitmap = SZ_1G | SZ_2M | SZ_4K,
+   .of_xlate = ipmmu_of_xlate,
 };
 
 #endif /* !CONFIG_ARM && CONFIG_IOMMU_DMA */
@@ -958,19 +954,6 @@ static struct iommu_group *ipmmu_find_gr
return group;
 }
 
-static int ipmmu_of_xlate_dma(struct device *dev,
- struct of_phandle_args *spec)
-{
-   /* If the IPMMU device is disabled in DT then return error
-* to make sure the of_iommu code does not install ops
-* even though the iommu device is disabled
-*/
-   if (!of_device_is_available(spec->np))
-   return -ENODEV;
-
-   return ipmmu_init_platform_device(dev);
-}
-
 static const struct iommu_ops ipmmu_ops = {
.domain_alloc = ipmmu_domain_alloc_dma,
.domain_free = ipmmu_domain_free_dma,
@@ -984,7 +967,7 @@ static const struct iommu_ops ipmmu_ops
.remove_device = ipmmu_remove_device_dma,
.device_group = ipmmu_find_group_dma,
.pgsize_bitmap = SZ_1G | SZ_2M | SZ_4K,
-   .of_xlate = ipmmu_of_xlate_dma,
+   .of_xlate = ipmmu_of_xlate,
 };
 
 #endif /* CONFIG_IOMMU_DMA */


[PATCH 01/04] iommu/ipmmu-vmsa: Use iommu_device_register()/unregister()

2017-06-15 Thread Magnus Damm
From: Magnus Damm 

Extend the driver to make use of iommu_device_register()/unregister()
functions together with iommu_device_set_ops() and iommu_set_fwnode().

These used to be part of the earlier posted 64-bit ARM (r8a7795) series but
it turns out that these days they are required on 32-bit ARM as well.

Signed-off-by: Magnus Damm 
---

 drivers/iommu/ipmmu-vmsa.c |   10 ++
 1 file changed, 10 insertions(+)

--- 0001/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-06-15 16:57:21.890607110 +0900
@@ -35,6 +35,7 @@
 struct ipmmu_vmsa_device {
struct device *dev;
void __iomem *base;
+   struct iommu_device iommu;
struct list_head list;
 
unsigned int num_utlbs;
@@ -1054,6 +1055,13 @@ static int ipmmu_probe(struct platform_d
 
ipmmu_device_reset(mmu);
 
+   ret = iommu_device_register(&mmu->iommu);
+   if (ret)
+   return ret;
+
+   iommu_device_set_ops(&mmu->iommu, &ipmmu_ops);
+   iommu_device_set_fwnode(&mmu->iommu, &pdev->dev.of_node->fwnode);
+
/*
 * We can't create the ARM mapping here as it requires the bus to have
 * an IOMMU, which only happens when bus_set_iommu() is called in
@@ -1077,6 +1085,8 @@ static int ipmmu_remove(struct platform_
list_del(&mmu->list);
spin_unlock(&ipmmu_devices_lock);
 
+   iommu_device_unregister(&mmu->iommu);
+
 #if defined(CONFIG_ARM) && !defined(CONFIG_IOMMU_DMA)
arm_iommu_release_mapping(mmu->mapping);
 #endif


[PATCH 03/04] iommu/ipmmu-vmsa: Use fwspec on both 32 and 64-bit ARM

2017-06-15 Thread Magnus Damm
From: Robin Murphy 

Consolidate the 32-bit and 64-bit code to make use of fwspec instead
of archdata for the 32-bit ARM case.

This is a simplified version of the fwspec handling code from Robin
posted as [PATCH] iommu/ipmmu-vmsa: Convert to iommu_fwspec

Signed-off-by: Robin Murphy 
Signed-off-by: Magnus Damm 
---

 drivers/iommu/ipmmu-vmsa.c |   21 +++--
 1 file changed, 3 insertions(+), 18 deletions(-)

--- 0010/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-06-15 17:29:00.290607110 +0900
@@ -73,22 +73,9 @@ static struct ipmmu_vmsa_domain *to_vmsa
return container_of(dom, struct ipmmu_vmsa_domain, io_domain);
 }
 
-
 static struct ipmmu_vmsa_iommu_priv *to_priv(struct device *dev)
 {
-#if defined(CONFIG_ARM)
-   return dev->archdata.iommu;
-#else
-   return dev->iommu_fwspec->iommu_priv;
-#endif
-}
-static void set_priv(struct device *dev, struct ipmmu_vmsa_iommu_priv *p)
-{
-#if defined(CONFIG_ARM)
-   dev->archdata.iommu = p;
-#else
-   dev->iommu_fwspec->iommu_priv = p;
-#endif
+   return dev->iommu_fwspec ? dev->iommu_fwspec->iommu_priv : NULL;
 }
 
 #define TLB_LOOP_TIMEOUT   100 /* 100us */
@@ -730,7 +717,7 @@ static int ipmmu_init_platform_device(st
priv->utlbs = utlbs;
priv->num_utlbs = num_utlbs;
priv->dev = dev;
-   set_priv(dev, priv);
+   dev->iommu_fwspec->iommu_priv = priv;
return 0;
 
 error:
@@ -887,14 +874,12 @@ static void ipmmu_domain_free_dma(struct
 
 static int ipmmu_add_device_dma(struct device *dev)
 {
-   struct iommu_fwspec *fwspec = dev->iommu_fwspec;
struct iommu_group *group;
 
/*
 * Only let through devices that have been verified in xlate()
-* We may get called with dev->iommu_fwspec set to NULL.
 */
-   if (!fwspec || !fwspec->iommu_priv)
+   if (!to_priv(dev))
return -ENODEV;
 
group = iommu_group_get_for_dev(dev);


[PATCH 04/04] iommu/ipmmu-vmsa: Replace local utlb code with fwspec ids

2017-06-15 Thread Magnus Damm
From: Magnus Damm 

Now when both 32-bit and 64-bit code inside the driver is using
fwspec it is possible to replace the utlb handling with fwspec ids
that get populated from ->of_xlate().

Suggested-by: Robin Murphy 
Signed-off-by: Magnus Damm 
---

 drivers/iommu/ipmmu-vmsa.c |  104 
 1 file changed, 19 insertions(+), 85 deletions(-)

--- 0013/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-06-15 18:32:27.580607110 +0900
@@ -19,6 +19,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -59,8 +60,6 @@ struct ipmmu_vmsa_domain {
 
 struct ipmmu_vmsa_iommu_priv {
struct ipmmu_vmsa_device *mmu;
-   unsigned int *utlbs;
-   unsigned int num_utlbs;
struct device *dev;
struct list_head list;
 };
@@ -550,13 +549,14 @@ static int ipmmu_attach_device(struct io
   struct device *dev)
 {
struct ipmmu_vmsa_iommu_priv *priv = to_priv(dev);
+   struct iommu_fwspec *fwspec = dev->iommu_fwspec;
struct ipmmu_vmsa_device *mmu = priv->mmu;
struct ipmmu_vmsa_domain *domain = to_vmsa_domain(io_domain);
unsigned long flags;
unsigned int i;
int ret = 0;
 
-   if (!mmu) {
+   if (!priv || !priv->mmu) {
dev_err(dev, "Cannot attach to IPMMU\n");
return -ENXIO;
}
@@ -583,8 +583,8 @@ static int ipmmu_attach_device(struct io
if (ret < 0)
return ret;
 
-   for (i = 0; i < priv->num_utlbs; ++i)
-   ipmmu_utlb_enable(domain, priv->utlbs[i]);
+   for (i = 0; i < fwspec->num_ids; ++i)
+   ipmmu_utlb_enable(domain, fwspec->ids[i]);
 
return 0;
 }
@@ -592,12 +592,12 @@ static int ipmmu_attach_device(struct io
 static void ipmmu_detach_device(struct iommu_domain *io_domain,
struct device *dev)
 {
-   struct ipmmu_vmsa_iommu_priv *priv = to_priv(dev);
+   struct iommu_fwspec *fwspec = dev->iommu_fwspec;
struct ipmmu_vmsa_domain *domain = to_vmsa_domain(io_domain);
unsigned int i;
 
-   for (i = 0; i < priv->num_utlbs; ++i)
-   ipmmu_utlb_disable(domain, priv->utlbs[i]);
+   for (i = 0; i < fwspec->num_ids; ++i)
+   ipmmu_utlb_disable(domain, fwspec->ids[i]);
 
/*
 * TODO: Optimize by disabling the context when no device is attached.
@@ -633,102 +633,36 @@ static phys_addr_t ipmmu_iova_to_phys(st
return domain->iop->iova_to_phys(domain->iop, iova);
 }
 
-static int ipmmu_find_utlbs(struct ipmmu_vmsa_device *mmu, struct device *dev,
-   unsigned int *utlbs, unsigned int num_utlbs)
-{
-   unsigned int i;
-
-   for (i = 0; i < num_utlbs; ++i) {
-   struct of_phandle_args args;
-   int ret;
-
-   ret = of_parse_phandle_with_args(dev->of_node, "iommus",
-"#iommu-cells", i, &args);
-   if (ret < 0)
-   return ret;
-
-   of_node_put(args.np);
-
-   if (args.np != mmu->dev->of_node || args.args_count != 1)
-   return -EINVAL;
-
-   utlbs[i] = args.args[0];
-   }
-
-   return 0;
-}
-
-static int ipmmu_init_platform_device(struct device *dev)
+static int ipmmu_init_platform_device(struct device *dev,
+ struct of_phandle_args *args)
 {
+   struct platform_device *ipmmu_pdev;
struct ipmmu_vmsa_iommu_priv *priv;
-   struct ipmmu_vmsa_device *mmu;
-   unsigned int *utlbs;
-   unsigned int i;
-   int num_utlbs;
-   int ret = -ENODEV;
 
/* Initialize once - xlate() will call multiple times */
if (to_priv(dev))
return 0;
 
-   /* Find the master corresponding to the device. */
-
-   num_utlbs = of_count_phandle_with_args(dev->of_node, "iommus",
-  "#iommu-cells");
-   if (num_utlbs < 0)
+   ipmmu_pdev = of_find_device_by_node(args->np);
+   if (!ipmmu_pdev)
return -ENODEV;
 
-   utlbs = kcalloc(num_utlbs, sizeof(*utlbs), GFP_KERNEL);
-   if (!utlbs)
-   return -ENOMEM;
-
-   spin_lock(&ipmmu_devices_lock);
-
-   list_for_each_entry(mmu, &ipmmu_devices, list) {
-   ret = ipmmu_find_utlbs(mmu, dev, utlbs, num_utlbs);
-   if (!ret) {
-   /*
-* TODO Take a reference to the MMU to protect
-* against device removal.
-*/
-   break;
-   }
-   }
-
-   spin_unlock(&ipmmu_devices_lock);
-
-   if (ret < 0)
-  

[PATCH 00/04] iommu/ipmmu-vmsa: 32-bit ARM update

2017-06-15 Thread Magnus Damm
iommu/ipmmu-vmsa: 32-bit ARM update

[PATCH 01/04] iommu/ipmmu-vmsa: Use iommu_device_register()/unregister()
[PATCH 02/04] iommu/ipmmu-vmsa: Consistent ->of_xlate() handling
[PATCH 03/04] iommu/ipmmu-vmsa: Use fwspec on both 32 and 64-bit ARM
[PATCH 04/04] iommu/ipmmu-vmsa: Replace local utlb code with fwspec ids

This series updates the IPMMU driver to make use of recent IOMMU framework
changes and also improves code sharing in the driver between the 32-bit and
64-bit dma-mapping architecture glue code.

Suggested-by: Robin Murphy  (Patch 2 and 4)
Signed-off-by: Robin Murphy  (Patch 3)
Signed-off-by: Magnus Damm 
---

 Developed on renesas-drivers-2017-06-13-v4.12-rc5 and rebased to next-20170614

 drivers/iommu/ipmmu-vmsa.c |  186 +++-
 1 file changed, 49 insertions(+), 137 deletions(-)


[PATCH] net: update undefined ->ndo_change_mtu() comment

2017-06-14 Thread Magnus Damm
From: Magnus Damm 

Update ->ndo_change_mtu() callback comment to remove text
about returning error in case of undefined callback. This
change makes the comment match the existing code behavior.

Signed-off-by: Magnus Damm 
---

 Applies on top of next-20170613

 include/linux/netdevice.h |3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

--- 0002/include/linux/netdevice.h
+++ work/include/linux/netdevice.h  2017-04-29 16:23:13.980607110 +0900
@@ -910,8 +910,7 @@ struct netdev_xdp {
  *
  * int (*ndo_change_mtu)(struct net_device *dev, int new_mtu);
  * Called when a user wants to change the Maximum Transfer Unit
- * of a device. If not defined, any request to change MTU will
- * will return an error.
+ * of a device.
  *
  * void (*ndo_tx_timeout)(struct net_device *dev);
  * Callback used when the transmitter has not made any progress


Re: [PATCH] via-rhine: add support for changing MTU

2017-06-13 Thread Magnus Damm
On Wed, Jun 14, 2017 at 6:33 AM, David Miller  wrote:
> From: Magnus Damm 
> Date: Wed, 14 Jun 2017 02:18:27 +0900
>
>> From: Magnus Damm 
>>
>> Allow adjusting the MTU for via-rhine devices in case of no TX alignment
>> buffer is used.
>>
>> Lightly tested on ALIX2D13 hardware by making use of VXLAN with MTU set
>> to 1500 on top of via-rhine devices with 1550 MTU. Without this patch
>> the VXLAN MTU is limited to less than 1500.
>>
>> Signed-off-by: Magnus Damm 
>
> Why is the TX alignment buffer such an obstacle?

Not such a big obstacle - I simply took the easy way out for this
first step. Adding support for MTU configuration when TX alignment is
required requires a bit more effort, and it also makes the driver
implementation slightly more complex.

The particular silicon version of via-rhine devices on my ALIX2D13
boards do not require the TX alignment workaround, but I should be
able to add some local test code for development purpose.

As for the TX alignment workaround implementation, when needed the
driver allocates rp->tx_bufs to PKT_BUF_SIZE * TX_RING_SIZE. To
support a larger MTU setting without increasing default memory usage
this TX side can be adjusted to manage buffers in a more dynamic way,
perhaps similar to the RX side with rp->rx_buf_sz.

> It would be so much nicer if this could be supported for all chip
> variants instead of some certain subset which users have no idea
> of figuring out.  It's a really bad user experience to set them
> up for failure like this.

Sure, I agree!

Will update the code with the TX alignment workaround and resend after
some much needed testing. It will most likely take some time, so
please don't block anything on this.

Cheers,

/ magnus


[PATCH] via-rhine: add support for changing MTU

2017-06-13 Thread Magnus Damm
From: Magnus Damm 

Allow adjusting the MTU for via-rhine devices in case of no TX alignment
buffer is used.

Lightly tested on ALIX2D13 hardware by making use of VXLAN with MTU set
to 1500 on top of via-rhine devices with 1550 MTU. Without this patch
the VXLAN MTU is limited to less than 1500.

Signed-off-by: Magnus Damm 
---

 Developed on top of next-20170613

 drivers/net/ethernet/via/via-rhine.c |   19 +++
 1 file changed, 19 insertions(+)

--- 0001/drivers/net/ethernet/via/via-rhine.c
+++ work/drivers/net/ethernet/via/via-rhine.c   2017-06-14 02:05:25.410607110 
+0900
@@ -518,6 +518,7 @@ static void rhine_get_stats64(struct net
 static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static const struct ethtool_ops netdev_ethtool_ops;
 static int  rhine_close(struct net_device *dev);
+static int rhine_change_mtu(struct net_device *dev, int new_mtu);
 static int rhine_vlan_rx_add_vid(struct net_device *dev,
 __be16 proto, u16 vid);
 static int rhine_vlan_rx_kill_vid(struct net_device *dev,
@@ -894,6 +895,7 @@ static const struct net_device_ops rhine
.ndo_set_mac_address = eth_mac_addr,
.ndo_do_ioctl= netdev_ioctl,
.ndo_tx_timeout  = rhine_tx_timeout,
+   .ndo_change_mtu  = rhine_change_mtu,
.ndo_vlan_rx_add_vid = rhine_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid= rhine_vlan_rx_kill_vid,
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -981,6 +983,14 @@ static int rhine_init_one_common(struct
 NETIF_F_HW_VLAN_CTAG_RX |
 NETIF_F_HW_VLAN_CTAG_FILTER;
 
+   /* Allow MTU configuration as long as TX alignment buffer is unused */
+   if (!(rp->quirks & rqRhineI)) {
+   /* Packets less than 64 octets will raise RDES0.RUNT. */
+   dev->min_mtu = ETH_ZLEN - ETH_HLEN;
+   /* Hardware has 11 bits of RDES0.Rx_Length including FCS. */
+   dev->max_mtu = 0x1fff - ETH_HLEN - ETH_FCS_LEN;
+   }
+
/* dev->name not defined before register_netdev()! */
rc = register_netdev(dev);
if (rc)
@@ -1399,6 +1409,15 @@ static void rhine_set_carrier(struct mii
   mii->force_media, netif_carrier_ok(dev));
 }
 
+static int rhine_change_mtu(struct net_device *dev, int new_mtu)
+{
+   if (dev->flags & IFF_UP)
+   return -EBUSY;
+
+   dev->mtu = new_mtu;
+   return 0;
+}
+
 /**
  * rhine_set_cam - set CAM multicast filters
  * @ioaddr: register block of this Rhine


Re: [PATCH v8 06/08] iommu/ipmmu-vmsa: Use fwspec iommu_priv on ARM64

2017-05-17 Thread Magnus Damm
Hi Robin,

On Wed, May 17, 2017 at 11:29 PM, Robin Murphy  wrote:
> Hi Magnus,
>
> On 17/05/17 11:07, Magnus Damm wrote:
>> From: Magnus Damm 
>>
>> Convert from archdata to iommu_priv via iommu_fwspec on ARM64 but
>> let 32-bit ARM keep on using archdata for now.
>>
>> Once the 32-bit ARM code and the IPMMU driver is able to move over
>> to CONFIG_IOMMU_DMA=y then coverting to fwspec via ->of_xlate() will
>> be easy.
>>
>> For now fwspec ids and num_ids are not used to allow code sharing between
>> 32-bit and 64-bit ARM code inside the driver.
>
> That's not what I meant at all - this just looks like a crazy
> unmaintainable mess that's making things that much harder to unpick in
> future.
>
> Leaving the existing code fossilised and building up half of a second
> separate driver around it wrapped in ifdefs is not only hideous, it's
> more work in the end than simply pulling things into the right shape to
> begin with. What I meant was to start with the below (compile-tested
> only), and add the of_xlate support on top. AFAICS the arm/arm64
> differences overall should only come down to a bit of special-casing in
> add_device(), and (optionally) whether you outright reject
> IOMMU_DOMAIN_DMA or not.
>
> Sorry, but I just can't agree with the two-drivers-in-one approach.

Thanks for checking the code and sorry to disappoint you by not using
->ids[] and ->num_ids right away. The two-drivers-on-one approach
comes from wanting to use the same IOMMU driver on both 32-bit and
64-bit ARM architectures but the former is lacking IOMMU_DMA support
upstream.

Obviously using ->ids[] and ->num_ids is the right forward, and in my
mind it is only a question of time and merge order. I'm more than
happy to make use of your patch but I'm wondering if it will work on
32-bit ARM and R-Car Gen2 that currently does not use ->of_xlate(). I
can see that you're using iommu_fwspec_init() so it might work right
out of the box. Thanks for your help cooking up the patch by the way.

>From my side I was hoping on doing one larger feature jump for 32-bit
ARM by moving over to IOMMU_DMA=y together with ->of_xlate()and fwspec
at the same time. Doing minor increments of the legacy code that is
still using special mapping code instead of OMMU_DMA=y in case of
32-bit ARM just feels like a lot of potential breakage and little gain
to me.

What's the plan for supporting IOMMU_DMA=y on 32-bit ARM? Anything I
can do to help? Or do you prefer minor increments on 32-bit ARM over
larger feature jumps?

Let me know what you think. My plan is to revisit this topic early next week.

Cheers,

/ magnus


[PATCH v8 07/08] iommu/ipmmu-vmsa: Drop LPAE Kconfig dependency

2017-05-17 Thread Magnus Damm
From: Magnus Damm 

Neither the ARM page table code enabled by IOMMU_IO_PGTABLE_LPAE
nor the IPMMU_VMSA driver actually depends on ARM_LPAE, so get
rid of the dependency.

Tested with ipmmu-vmsa on r8a7794 ALT and a kernel config using:
 # CONFIG_ARM_LPAE is not set

Signed-off-by: Magnus Damm 
Acked-by: Laurent Pinchart 
Reviewed-by: Joerg Roedel 
---

 Changes since V7:
 - None

 drivers/iommu/Kconfig |1 -
 1 file changed, 1 deletion(-)

--- 0010/drivers/iommu/Kconfig
+++ work/drivers/iommu/Kconfig  2017-05-17 16:45:15.530607110 +0900
@@ -275,7 +275,6 @@ config EXYNOS_IOMMU_DEBUG
 config IPMMU_VMSA
bool "Renesas VMSA-compatible IPMMU"
depends on ARM || IOMMU_DMA
-   depends on ARM_LPAE
depends on ARCH_RENESAS || COMPILE_TEST
select IOMMU_API
select IOMMU_IO_PGTABLE_LPAE


[PATCH v8 08/08] iommu/ipmmu-vmsa: Fix pgsize_bitmap semicolon typo

2017-05-17 Thread Magnus Damm
From: Magnus Damm 

Fix comma-instead-of-semicolon typo error present
in the latest version of the IPMMU driver.

Signed-off-by: Magnus Damm 
---

 Earlier posted as:
 [PATCH] iommu/ipmmu-vmsa: Fix pgsize_bitmap semicolon typo

 drivers/iommu/ipmmu-vmsa.c |2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- 0014/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-05-17 16:50:02.850607110 +0900
@@ -358,7 +358,7 @@ static int ipmmu_domain_init_context(str
 * non-secure mode.
 */
domain->cfg.quirks = IO_PGTABLE_QUIRK_ARM_NS;
-   domain->cfg.pgsize_bitmap = SZ_1G | SZ_2M | SZ_4K,
+   domain->cfg.pgsize_bitmap = SZ_1G | SZ_2M | SZ_4K;
domain->cfg.ias = 32;
domain->cfg.oas = 40;
domain->cfg.tlb = &ipmmu_gather_ops;


[PATCH v8 06/08] iommu/ipmmu-vmsa: Use fwspec iommu_priv on ARM64

2017-05-17 Thread Magnus Damm
From: Magnus Damm 

Convert from archdata to iommu_priv via iommu_fwspec on ARM64 but
let 32-bit ARM keep on using archdata for now.

Once the 32-bit ARM code and the IPMMU driver is able to move over
to CONFIG_IOMMU_DMA=y then coverting to fwspec via ->of_xlate() will
be easy.

For now fwspec ids and num_ids are not used to allow code sharing between
32-bit and 64-bit ARM code inside the driver.

Signed-off-by: Magnus Damm 
---

 Changes since V7:
 - Rewrote code to use iommu_fwspec, thanks Robin!
 - Dropped reviewed-by from Joerg, also skipped tag from Geert

 drivers/iommu/ipmmu-vmsa.c |   97 ++--
 1 file changed, 58 insertions(+), 39 deletions(-)

--- 0011/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-05-17 16:45:07.510607110 +0900
@@ -56,7 +56,7 @@ struct ipmmu_vmsa_domain {
spinlock_t lock;/* Protects mappings */
 };
 
-struct ipmmu_vmsa_archdata {
+struct ipmmu_vmsa_iommu_priv {
struct ipmmu_vmsa_device *mmu;
unsigned int *utlbs;
unsigned int num_utlbs;
@@ -72,6 +72,24 @@ static struct ipmmu_vmsa_domain *to_vmsa
return container_of(dom, struct ipmmu_vmsa_domain, io_domain);
 }
 
+
+static struct ipmmu_vmsa_iommu_priv *to_priv(struct device *dev)
+{
+#if defined(CONFIG_ARM)
+   return dev->archdata.iommu;
+#else
+   return dev->iommu_fwspec->iommu_priv;
+#endif
+}
+static void set_priv(struct device *dev, struct ipmmu_vmsa_iommu_priv *p)
+{
+#if defined(CONFIG_ARM)
+   dev->archdata.iommu = p;
+#else
+   dev->iommu_fwspec->iommu_priv = p;
+#endif
+}
+
 #define TLB_LOOP_TIMEOUT   100 /* 100us */
 
 /* 
-
@@ -543,8 +561,8 @@ static void ipmmu_domain_free(struct iom
 static int ipmmu_attach_device(struct iommu_domain *io_domain,
   struct device *dev)
 {
-   struct ipmmu_vmsa_archdata *archdata = dev->archdata.iommu;
-   struct ipmmu_vmsa_device *mmu = archdata->mmu;
+   struct ipmmu_vmsa_iommu_priv *priv = to_priv(dev);
+   struct ipmmu_vmsa_device *mmu = priv->mmu;
struct ipmmu_vmsa_domain *domain = to_vmsa_domain(io_domain);
unsigned long flags;
unsigned int i;
@@ -577,8 +595,8 @@ static int ipmmu_attach_device(struct io
if (ret < 0)
return ret;
 
-   for (i = 0; i < archdata->num_utlbs; ++i)
-   ipmmu_utlb_enable(domain, archdata->utlbs[i]);
+   for (i = 0; i < priv->num_utlbs; ++i)
+   ipmmu_utlb_enable(domain, priv->utlbs[i]);
 
return 0;
 }
@@ -586,12 +604,12 @@ static int ipmmu_attach_device(struct io
 static void ipmmu_detach_device(struct iommu_domain *io_domain,
struct device *dev)
 {
-   struct ipmmu_vmsa_archdata *archdata = dev->archdata.iommu;
+   struct ipmmu_vmsa_iommu_priv *priv = to_priv(dev);
struct ipmmu_vmsa_domain *domain = to_vmsa_domain(io_domain);
unsigned int i;
 
-   for (i = 0; i < archdata->num_utlbs; ++i)
-   ipmmu_utlb_disable(domain, archdata->utlbs[i]);
+   for (i = 0; i < priv->num_utlbs; ++i)
+   ipmmu_utlb_disable(domain, priv->utlbs[i]);
 
/*
 * TODO: Optimize by disabling the context when no device is attached.
@@ -654,7 +672,7 @@ static int ipmmu_find_utlbs(struct ipmmu
 
 static int ipmmu_init_platform_device(struct device *dev)
 {
-   struct ipmmu_vmsa_archdata *archdata;
+   struct ipmmu_vmsa_iommu_priv *priv;
struct ipmmu_vmsa_device *mmu;
unsigned int *utlbs;
unsigned int i;
@@ -697,17 +715,17 @@ static int ipmmu_init_platform_device(st
}
}
 
-   archdata = kzalloc(sizeof(*archdata), GFP_KERNEL);
-   if (!archdata) {
+   priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+   if (!priv) {
ret = -ENOMEM;
goto error;
}
 
-   archdata->mmu = mmu;
-   archdata->utlbs = utlbs;
-   archdata->num_utlbs = num_utlbs;
-   archdata->dev = dev;
-   dev->archdata.iommu = archdata;
+   priv->mmu = mmu;
+   priv->utlbs = utlbs;
+   priv->num_utlbs = num_utlbs;
+   priv->dev = dev;
+   set_priv(dev, priv);
return 0;
 
 error:
@@ -727,12 +745,11 @@ static struct iommu_domain *ipmmu_domain
 
 static int ipmmu_add_device(struct device *dev)
 {
-   struct ipmmu_vmsa_archdata *archdata;
struct ipmmu_vmsa_device *mmu = NULL;
struct iommu_group *group;
int ret;
 
-   if (dev->archdata.iommu) {
+   if (to_priv(dev)) {
dev_warn(dev, "IOMMU driver already assigned to device %s\n",
 dev_name(dev));
return -EINVAL;
@@ -768,8 +785,7 @@ static int ipmmu_add_device(struct dev

[PATCH v8 05/08] iommu/ipmmu-vmsa: Add new IOMMU_DOMAIN_DMA ops

2017-05-17 Thread Magnus Damm
From: Magnus Damm 

Introduce an alternative set of iommu_ops suitable for 64-bit ARM
as well as 32-bit ARM when CONFIG_IOMMU_DMA=y. Also adjust the
Kconfig to depend on ARM or IOMMU_DMA. Initialize the device
from ->xlate() when CONFIG_IOMMU_DMA=y.

Signed-off-by: Magnus Damm 
---

 Changes since V7:
 - None

 drivers/iommu/Kconfig  |1 
 drivers/iommu/ipmmu-vmsa.c |  164 +---
 2 files changed, 156 insertions(+), 9 deletions(-)

--- 0001/drivers/iommu/Kconfig
+++ work/drivers/iommu/Kconfig  2017-05-17 16:41:43.030607110 +0900
@@ -274,6 +274,7 @@ config EXYNOS_IOMMU_DEBUG
 
 config IPMMU_VMSA
bool "Renesas VMSA-compatible IPMMU"
+   depends on ARM || IOMMU_DMA
depends on ARM_LPAE
depends on ARCH_RENESAS || COMPILE_TEST
select IOMMU_API
--- 0009/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-05-17 16:42:02.730607110 +0900
@@ -10,6 +10,7 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -22,8 +23,10 @@
 #include 
 #include 
 
+#if defined(CONFIG_ARM) && !defined(CONFIG_IOMMU_DMA)
 #include 
 #include 
+#endif
 
 #include "io-pgtable.h"
 
@@ -57,6 +60,8 @@ struct ipmmu_vmsa_archdata {
struct ipmmu_vmsa_device *mmu;
unsigned int *utlbs;
unsigned int num_utlbs;
+   struct device *dev;
+   struct list_head list;
 };
 
 static DEFINE_SPINLOCK(ipmmu_devices_lock);
@@ -522,14 +527,6 @@ static struct iommu_domain *__ipmmu_doma
return &domain->io_domain;
 }
 
-static struct iommu_domain *ipmmu_domain_alloc(unsigned type)
-{
-   if (type != IOMMU_DOMAIN_UNMANAGED)
-   return NULL;
-
-   return __ipmmu_domain_alloc(type);
-}
-
 static void ipmmu_domain_free(struct iommu_domain *io_domain)
 {
struct ipmmu_vmsa_domain *domain = to_vmsa_domain(io_domain);
@@ -572,7 +569,8 @@ static int ipmmu_attach_device(struct io
dev_err(dev, "Can't attach IPMMU %s to domain on IPMMU %s\n",
dev_name(mmu->dev), dev_name(domain->mmu->dev));
ret = -EINVAL;
-   }
+   } else
+   dev_info(dev, "Reusing IPMMU context %u\n", domain->context_id);
 
spin_unlock_irqrestore(&domain->lock, flags);
 
@@ -708,6 +706,7 @@ static int ipmmu_init_platform_device(st
archdata->mmu = mmu;
archdata->utlbs = utlbs;
archdata->num_utlbs = num_utlbs;
+   archdata->dev = dev;
dev->archdata.iommu = archdata;
return 0;
 
@@ -716,6 +715,16 @@ error:
return ret;
 }
 
+#if defined(CONFIG_ARM) && !defined(CONFIG_IOMMU_DMA)
+
+static struct iommu_domain *ipmmu_domain_alloc(unsigned type)
+{
+   if (type != IOMMU_DOMAIN_UNMANAGED)
+   return NULL;
+
+   return __ipmmu_domain_alloc(type);
+}
+
 static int ipmmu_add_device(struct device *dev)
 {
struct ipmmu_vmsa_archdata *archdata;
@@ -825,6 +834,141 @@ static const struct iommu_ops ipmmu_ops
.pgsize_bitmap = SZ_1G | SZ_2M | SZ_4K,
 };
 
+#endif /* !CONFIG_ARM && CONFIG_IOMMU_DMA */
+
+#ifdef CONFIG_IOMMU_DMA
+
+static DEFINE_SPINLOCK(ipmmu_slave_devices_lock);
+static LIST_HEAD(ipmmu_slave_devices);
+
+static struct iommu_domain *ipmmu_domain_alloc_dma(unsigned type)
+{
+   struct iommu_domain *io_domain = NULL;
+
+   switch (type) {
+   case IOMMU_DOMAIN_UNMANAGED:
+   io_domain = __ipmmu_domain_alloc(type);
+   break;
+
+   case IOMMU_DOMAIN_DMA:
+   io_domain = __ipmmu_domain_alloc(type);
+   if (io_domain)
+   iommu_get_dma_cookie(io_domain);
+   break;
+   }
+
+   return io_domain;
+}
+
+static void ipmmu_domain_free_dma(struct iommu_domain *io_domain)
+{
+   switch (io_domain->type) {
+   case IOMMU_DOMAIN_DMA:
+   iommu_put_dma_cookie(io_domain);
+   /* fall-through */
+   default:
+   ipmmu_domain_free(io_domain);
+   break;
+   }
+}
+
+static int ipmmu_add_device_dma(struct device *dev)
+{
+   struct ipmmu_vmsa_archdata *archdata = dev->archdata.iommu;
+   struct iommu_group *group;
+
+   /* The device has been verified in xlate() */
+   if (!archdata)
+   return -ENODEV;
+
+   group = iommu_group_get_for_dev(dev);
+   if (IS_ERR(group))
+   return PTR_ERR(group);
+
+   spin_lock(&ipmmu_slave_devices_lock);
+   list_add(&archdata->list, &ipmmu_slave_devices);
+   spin_unlock(&ipmmu_slave_devices_lock);
+   return 0;
+}
+
+static void ipmmu_remove_device_dma(struct device *dev)
+{
+   struct ipmmu_vmsa_archdata *archdata = dev->archdata.iommu;
+
+   spin_lock(&ipmmu_slave_devices_lock);
+   list_del(&archdata->list);
+   spin_unlock(&ipmm

[PATCH v8 02/08] iommu/ipmmu-vmsa: Rework interrupt code and use bitmap for context

2017-05-17 Thread Magnus Damm
From: Magnus Damm 

Introduce a bitmap for context handing and convert the
interrupt routine to handle all registered contexts.

At this point the number of contexts are still limited.

Also remove the use of the ARM specific mapping variable
from ipmmu_irq() to allow compile on ARM64.

Signed-off-by: Magnus Damm 
Reviewed-by: Joerg Roedel 
---

 Changes since V7:
 - None

 drivers/iommu/ipmmu-vmsa.c |   76 ++--
 1 file changed, 66 insertions(+), 10 deletions(-)

--- 0002/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-05-17 16:33:02.380607110 +0900
@@ -8,6 +8,7 @@
  * the Free Software Foundation; version 2 of the License.
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -26,12 +27,17 @@
 
 #include "io-pgtable.h"
 
+#define IPMMU_CTX_MAX 1
+
 struct ipmmu_vmsa_device {
struct device *dev;
void __iomem *base;
struct list_head list;
 
unsigned int num_utlbs;
+   spinlock_t lock;/* Protects ctx and domains[] */
+   DECLARE_BITMAP(ctx, IPMMU_CTX_MAX);
+   struct ipmmu_vmsa_domain *domains[IPMMU_CTX_MAX];
 
struct dma_iommu_mapping *mapping;
 };
@@ -293,9 +299,29 @@ static struct iommu_gather_ops ipmmu_gat
  * Domain/Context Management
  */
 
+static int ipmmu_domain_allocate_context(struct ipmmu_vmsa_device *mmu,
+struct ipmmu_vmsa_domain *domain)
+{
+   unsigned long flags;
+   int ret;
+
+   spin_lock_irqsave(&mmu->lock, flags);
+
+   ret = find_first_zero_bit(mmu->ctx, IPMMU_CTX_MAX);
+   if (ret != IPMMU_CTX_MAX) {
+   mmu->domains[ret] = domain;
+   set_bit(ret, mmu->ctx);
+   }
+
+   spin_unlock_irqrestore(&mmu->lock, flags);
+
+   return ret;
+}
+
 static int ipmmu_domain_init_context(struct ipmmu_vmsa_domain *domain)
 {
u64 ttbr;
+   int ret;
 
/*
 * Allocate the page table operations.
@@ -327,10 +353,15 @@ static int ipmmu_domain_init_context(str
return -EINVAL;
 
/*
-* TODO: When adding support for multiple contexts, find an unused
-* context.
+* Find an unused context.
 */
-   domain->context_id = 0;
+   ret = ipmmu_domain_allocate_context(domain->mmu, domain);
+   if (ret == IPMMU_CTX_MAX) {
+   free_io_pgtable_ops(domain->iop);
+   return -EBUSY;
+   }
+
+   domain->context_id = ret;
 
/* TTBR0 */
ttbr = domain->cfg.arm_lpae_s1_cfg.ttbr[0];
@@ -372,6 +403,19 @@ static int ipmmu_domain_init_context(str
return 0;
 }
 
+static void ipmmu_domain_free_context(struct ipmmu_vmsa_device *mmu,
+ unsigned int context_id)
+{
+   unsigned long flags;
+
+   spin_lock_irqsave(&mmu->lock, flags);
+
+   clear_bit(context_id, mmu->ctx);
+   mmu->domains[context_id] = NULL;
+
+   spin_unlock_irqrestore(&mmu->lock, flags);
+}
+
 static void ipmmu_domain_destroy_context(struct ipmmu_vmsa_domain *domain)
 {
/*
@@ -382,6 +426,7 @@ static void ipmmu_domain_destroy_context
 */
ipmmu_ctx_write(domain, IMCTR, IMCTR_FLUSH);
ipmmu_tlb_sync(domain);
+   ipmmu_domain_free_context(domain->mmu, domain->context_id);
 }
 
 /* 
-
@@ -439,16 +484,25 @@ static irqreturn_t ipmmu_domain_irq(stru
 static irqreturn_t ipmmu_irq(int irq, void *dev)
 {
struct ipmmu_vmsa_device *mmu = dev;
-   struct iommu_domain *io_domain;
-   struct ipmmu_vmsa_domain *domain;
+   irqreturn_t status = IRQ_NONE;
+   unsigned int i;
+   unsigned long flags;
 
-   if (!mmu->mapping)
-   return IRQ_NONE;
+   spin_lock_irqsave(&mmu->lock, flags);
+
+   /*
+* Check interrupts for all active contexts.
+*/
+   for (i = 0; i < IPMMU_CTX_MAX; i++) {
+   if (!mmu->domains[i])
+   continue;
+   if (ipmmu_domain_irq(mmu->domains[i]) == IRQ_HANDLED)
+   status = IRQ_HANDLED;
+   }
 
-   io_domain = mmu->mapping->domain;
-   domain = to_vmsa_domain(io_domain);
+   spin_unlock_irqrestore(&mmu->lock, flags);
 
-   return ipmmu_domain_irq(domain);
+   return status;
 }
 
 /* 
-
@@ -776,6 +830,8 @@ static int ipmmu_probe(struct platform_d
 
mmu->dev = &pdev->dev;
mmu->num_utlbs = 32;
+   spin_lock_init(&mmu->lock);
+   bitmap_zero(mmu->ctx, IPMMU_CTX_MAX);
 
/* Map I/O memory and request IRQ. */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);


[PATCH v8 01/08] iommu/ipmmu-vmsa: Remove platform data handling

2017-05-17 Thread Magnus Damm
From: Magnus Damm 

The IPMMU driver is using DT these days, and platform data is no longer
used by the driver. Remove unused code.

Signed-off-by: Magnus Damm 
Reviewed-by: Laurent Pinchart 
Reviewed-by: Joerg Roedel 
Reviewed-by: Geert Uytterhoeven 
---

 Changes since V7:
 - Added Reviewed-by from Geert - Thanks!

 drivers/iommu/ipmmu-vmsa.c |5 -
 1 file changed, 5 deletions(-)

--- 0001/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-05-17 16:30:57.620607110 +0900
@@ -768,11 +768,6 @@ static int ipmmu_probe(struct platform_d
int irq;
int ret;
 
-   if (!IS_ENABLED(CONFIG_OF) && !pdev->dev.platform_data) {
-   dev_err(&pdev->dev, "missing platform data\n");
-   return -EINVAL;
-   }
-
mmu = devm_kzalloc(&pdev->dev, sizeof(*mmu), GFP_KERNEL);
if (!mmu) {
dev_err(&pdev->dev, "cannot allocate device data\n");


[PATCH v8 04/08] iommu/ipmmu-vmsa: Break out domain allocation code

2017-05-17 Thread Magnus Damm
From: Magnus Damm 

Break out the domain allocation code into a separate function.

This is preparation for future code sharing.

Signed-off-by: Magnus Damm 
Reviewed-by: Joerg Roedel 
Reviewed-by: Geert Uytterhoeven 
---

 Changes since V7:
 - Added Reviewed-by from Geert - Thanks!

 drivers/iommu/ipmmu-vmsa.c |   13 +
 1 file changed, 9 insertions(+), 4 deletions(-)

--- 0006/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-05-17 16:39:05.380607110 +0900
@@ -509,13 +509,10 @@ static irqreturn_t ipmmu_irq(int irq, vo
  * IOMMU Operations
  */
 
-static struct iommu_domain *ipmmu_domain_alloc(unsigned type)
+static struct iommu_domain *__ipmmu_domain_alloc(unsigned type)
 {
struct ipmmu_vmsa_domain *domain;
 
-   if (type != IOMMU_DOMAIN_UNMANAGED)
-   return NULL;
-
domain = kzalloc(sizeof(*domain), GFP_KERNEL);
if (!domain)
return NULL;
@@ -525,6 +522,14 @@ static struct iommu_domain *ipmmu_domain
return &domain->io_domain;
 }
 
+static struct iommu_domain *ipmmu_domain_alloc(unsigned type)
+{
+   if (type != IOMMU_DOMAIN_UNMANAGED)
+   return NULL;
+
+   return __ipmmu_domain_alloc(type);
+}
+
 static void ipmmu_domain_free(struct iommu_domain *io_domain)
 {
struct ipmmu_vmsa_domain *domain = to_vmsa_domain(io_domain);


[PATCH v8 00/08] iommu/ipmmu-vmsa: IPMMU multi-arch update V8

2017-05-17 Thread Magnus Damm
iommu/ipmmu-vmsa: IPMMU multi-arch update V8

[PATCH v8 01/08] iommu/ipmmu-vmsa: Remove platform data handling
[PATCH v8 02/08] iommu/ipmmu-vmsa: Rework interrupt code and use bitmap for 
context
[PATCH v8 03/08] iommu/ipmmu-vmsa: Break out utlb parsing code
[PATCH v8 04/08] iommu/ipmmu-vmsa: Break out domain allocation code
[PATCH v8 05/08] iommu/ipmmu-vmsa: Add new IOMMU_DOMAIN_DMA ops
[PATCH v8 06/08] iommu/ipmmu-vmsa: Use fwspec iommu_priv on ARM64
[PATCH v8 07/08] iommu/ipmmu-vmsa: Drop LPAE Kconfig dependency
[PATCH v8 08/08] iommu/ipmmu-vmsa: Fix pgsize_bitmap semicolon typo

These patches update the IPMMU driver with a modifications to support
build on multiple architectures. In the process of doing so the interrupt
code gets reworked, the foundation for supporting multiple contexts are
added and in case of CONFIG_IOMMU_DMA=y (on 64-bit or 32-bit ARM) devices
are grouped together and handled via ->xlate(). In this verison fwspec is
used on 64-bit ARM instead of archdata. Support for existing 32-bit ARM
SoCs from R-Car Gen2 is kept as-is.

Changes since V7:
 - Rebased on top of v4.12-rc1
 - Added Reviewed-by from Geert to patch 1/8 and 4/8, thanks!
 - Reworked patch 6/8 to use fwspec, thanks Robin!
 - Added patch 8/8

Changes since V6:
 - Rebased on top of v4.11-rc1 and the following fast-tracked change:
   3b6bb5b iommu/ipmmu-vmsa: Restrict IOMMU Domain Geometry to 32-bit address 
spac
 - Updated patch 5/7 to roll in a few patches from other series
   See individual patch for more details
 - Build tested on 32-bit and 64-bit ARM
 - Run time tested on 64-bit ARM (with additional SoC-specific patches)

Changes since V5:
 - Rebased series on top of next-20161019
 - Updated patch 5/7 to simplify domain allocation/free code - thanks Joerg!
 - Added reviewed-by tag from Joerg for patch 1-4 and 6-7.
 
Changes since V4:
 - Updated patch 3/7 to work on top on the following commit in next-20160920:
   b1e2afc iommu/ipmmu-vmsa: Fix wrong error handle of ipmmu_add_device
 - Add Kconfig hunk to patch 5/7 to avoid undeclared ipmmu_ops if COMPILE_TEST
 - Rebased patch 7/7 to fit on top of new Kconfig bits in 5/7

Changes since V3:
 - Updated patch 3/7 to fix hang-on-boot issue on 32-bit ARM - thanks Geert!
 - Reworked group parameter handling in patch 3/7 and 5/7.
 - Added patch 6/7 to fix build of the driver on s390/tile/um architectures

Changes since V2:
 - Got rid of patch 3 from the V2 however patch 1, 2 and 4 are kept.
 - V3 patch 3, 4 and 5 come from
   [PATCH 00/04] iommu/ipmmu-vmsa: IPMMU CONFIG_IOMMU_DMA update
 - Patch 5 has been reworked to include patch 3 of the V1 of this series 

Changes since V1:
 - Got rid of patch 2 and 3 from initial series
 - Updated bitmap code locking and also used lighter bitop functions
 - Updated the Kconfig bits to apply on top of ARCH_RENESAS

Signed-off-by: Magnus Damm 
---

 Developed on top of a95cfad (v4.12-rc1 + fixes):

 Compile tested on 32-bit and 64-bit ARM

 Run time tested on 64-bit ARM r8a7796 Salvator-X

 drivers/iommu/Kconfig  |2 
 drivers/iommu/ipmmu-vmsa.c |  421 ++--
 2 files changed, 331 insertions(+), 92 deletions(-)


[PATCH v8 03/08] iommu/ipmmu-vmsa: Break out utlb parsing code

2017-05-17 Thread Magnus Damm
From: Magnus Damm 

Break out the utlb parsing code and dev_data allocation into a
separate function. This is preparation for future code sharing.

Signed-off-by: Magnus Damm 
Reviewed-by: Joerg Roedel 
---

 Changes since V7:
 - Free archdata and utlbs in case of error

 drivers/iommu/ipmmu-vmsa.c |   64 
 1 file changed, 41 insertions(+), 23 deletions(-)

--- 0004/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-05-17 16:37:29.080607110 +0900
@@ -649,22 +649,15 @@ static int ipmmu_find_utlbs(struct ipmmu
return 0;
 }
 
-static int ipmmu_add_device(struct device *dev)
+static int ipmmu_init_platform_device(struct device *dev)
 {
struct ipmmu_vmsa_archdata *archdata;
struct ipmmu_vmsa_device *mmu;
-   struct iommu_group *group = NULL;
unsigned int *utlbs;
unsigned int i;
int num_utlbs;
int ret = -ENODEV;
 
-   if (dev->archdata.iommu) {
-   dev_warn(dev, "IOMMU driver already assigned to device %s\n",
-dev_name(dev));
-   return -EINVAL;
-   }
-
/* Find the master corresponding to the device. */
 
num_utlbs = of_count_phandle_with_args(dev->of_node, "iommus",
@@ -701,6 +694,36 @@ static int ipmmu_add_device(struct devic
}
}
 
+   archdata = kzalloc(sizeof(*archdata), GFP_KERNEL);
+   if (!archdata) {
+   ret = -ENOMEM;
+   goto error;
+   }
+
+   archdata->mmu = mmu;
+   archdata->utlbs = utlbs;
+   archdata->num_utlbs = num_utlbs;
+   dev->archdata.iommu = archdata;
+   return 0;
+
+error:
+   kfree(utlbs);
+   return ret;
+}
+
+static int ipmmu_add_device(struct device *dev)
+{
+   struct ipmmu_vmsa_archdata *archdata;
+   struct ipmmu_vmsa_device *mmu = NULL;
+   struct iommu_group *group;
+   int ret;
+
+   if (dev->archdata.iommu) {
+   dev_warn(dev, "IOMMU driver already assigned to device %s\n",
+dev_name(dev));
+   return -EINVAL;
+   }
+
/* Create a device group and add the device to it. */
group = iommu_group_alloc();
if (IS_ERR(group)) {
@@ -718,16 +741,9 @@ static int ipmmu_add_device(struct devic
goto error;
}
 
-   archdata = kzalloc(sizeof(*archdata), GFP_KERNEL);
-   if (!archdata) {
-   ret = -ENOMEM;
+   ret = ipmmu_init_platform_device(dev);
+   if (ret < 0)
goto error;
-   }
-
-   archdata->mmu = mmu;
-   archdata->utlbs = utlbs;
-   archdata->num_utlbs = num_utlbs;
-   dev->archdata.iommu = archdata;
 
/*
 * Create the ARM mapping, used by the ARM DMA mapping core to allocate
@@ -738,6 +754,8 @@ static int ipmmu_add_device(struct devic
 * - Make the mapping size configurable ? We currently use a 2GB mapping
 *   at a 1GB offset to ensure that NULL VAs will fault.
 */
+   archdata = dev->archdata.iommu;
+   mmu = archdata->mmu;
if (!mmu->mapping) {
struct dma_iommu_mapping *mapping;
 
@@ -762,16 +780,16 @@ static int ipmmu_add_device(struct devic
return 0;
 
 error:
-   arm_iommu_release_mapping(mmu->mapping);
-
-   kfree(dev->archdata.iommu);
-   kfree(utlbs);
-
-   dev->archdata.iommu = NULL;
+   if (mmu)
+   arm_iommu_release_mapping(mmu->mapping);
 
if (!IS_ERR_OR_NULL(group))
iommu_group_remove_device(dev);
 
+   kfree(archdata->utlbs);
+   kfree(archdata);
+   dev->archdata.iommu = NULL;
+
return ret;
 }
 


[PATCH] iommu/ipmmu-vmsa: Fix pgsize_bitmap semicolon typo

2017-04-20 Thread Magnus Damm
From: Magnus Damm 

Fix comman-instead-of-semicolon typo error present
in the latest version of the IPMMU driver.

Will in the future be rolled into next driver update.

Signed-off-by: Magnus Damm 
---

 Applies on top of renesas-drivers-2017-04-18-v4.11-rc7 or -next plus:
 [PATCH v7 00/07] iommu/ipmmu-vmsa: IPMMU multi-arch update V7
 [PATCH v3 00/09] iommu/ipmmu-vmsa: r8a7795 support V3
 [PATCH v3 0/3] iommu/ipmmu-vmsa: r8a7796 support V3

 drivers/iommu/ipmmu-vmsa.c |2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- 0001/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-04-20 22:30:07.000607110 +0900
@@ -431,7 +431,7 @@ static int ipmmu_domain_init_context(str
 * non-secure mode.
 */
domain->cfg.quirks = IO_PGTABLE_QUIRK_ARM_NS;
-   domain->cfg.pgsize_bitmap = SZ_1G | SZ_2M | SZ_4K,
+   domain->cfg.pgsize_bitmap = SZ_1G | SZ_2M | SZ_4K;
domain->cfg.ias = 32;
domain->cfg.oas = 40;
domain->cfg.tlb = &ipmmu_gather_ops;


[PATCH 0/3] dmaengine: rcar-dmac: Priority and slow mode prototypes

2017-03-13 Thread Magnus Damm
dmaengine: rcar-dmac: Priority and slow mode prototypes

[PATCH 1/3] dmaengine: rcar-dmac: Priority handling prototype
[PATCH 2/3] dmaengine: rcar-dmac: Slow mode prototype
[PATCH 3/3] arm64: dts: r8a7795: Use slow mode for TX on SCIF2/DEBUG1

This series implements prototype support for priority handling and slow
mode for the rcar-dmac driver and in particular the SYS-DMAC hardware
found on several R-Car devices.

The priority handling uses MID/RID values to determine if channels
below to RX or TX sides. The case of RX is unchanged and as low channel
number as possible is used to ensure high priority. New with patch 1/3
is that TX is allocated with highest channel number first to force low
priority. Some ugly layer violations are implemented to keep track of
which channels that are in use and which that are free.

The slow mode simply extends the MID/RID value to allow encoding a 4-bit
value in bit 8-11 to specify the SLM bit value. With this value set the
channel associated with the device will be processed slower. The idea is
that the slow mode can be used for testing to force underruns to harden
other parts of the system.

The third patch shows how to make use of the second patch

These patches probably need a bit more effort to be beaten into shape
for upstream merge. So simply treat these as experimental test code.

Not-Yet-Signed-off-by: Magnus Damm 
---

 Developed on top of renesas-drivers-2017-02-21-v4.10

 arch/arm64/boot/dts/renesas/r8a7795.dtsi |2
 drivers/dma/sh/rcar-dmac.c   |  109 +++---
 2 files changed, 101 insertions(+), 10 deletions(-)
   


[PATCH 1/3] dmaengine: rcar-dmac: Priority handling prototype

2017-03-13 Thread Magnus Damm
From: Magnus Damm 

The priority handling uses MID/RID values to determine if channels
below to RX or TX sides. The case of RX is unchanged and as low channel
number as possible is used to ensure high priority. New with this code
is that TX is allocated with highest channel number first to force low
priority. Some ugly layer violations are implemented to keep track of
which channels that are in use and which that are free.

Not-Yet-Signed-off-by: Magnus Damm 
---

 drivers/dma/sh/rcar-dmac.c |   96 +---
 1 file changed, 90 insertions(+), 6 deletions(-)

--- 0001/drivers/dma/sh/rcar-dmac.c
+++ work/drivers/dma/sh/rcar-dmac.c 2017-03-13 23:15:01.890607110 +0900
@@ -27,6 +27,11 @@
 #include "../dmaengine.h"
 
 /*
+ * Maximum number of channels this driver handles
+ */
+#define RCAR_DMAC_CHANNELS_MAX 100
+
+/*
  * struct rcar_dmac_xfer_chunk - Descriptor for a hardware transfer
  * @node: entry in the parent's chunks list
  * @src_addr: device source address
@@ -203,8 +208,20 @@ struct rcar_dmac {
struct rcar_dmac_chan *channels;
 
DECLARE_BITMAP(modules, 256);
+   DECLARE_BITMAP(ch_in_use, RCAR_DMAC_CHANNELS_MAX);
 };
 
+/*
+ * The ch_in_use bitmap is in reverse order to allow fast look up
+ * of the last available channel via find_next_zero_bit().
+ */
+static inline unsigned int rcar_dmac_chan_to_bit(struct dma_chan *chan)
+{
+   struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan);
+
+   return (RCAR_DMAC_CHANNELS_MAX - 1) - rchan->index;
+}
+
 #define to_rcar_dmac(d)container_of(d, struct rcar_dmac, 
engine)
 
 /* 
-
@@ -965,6 +982,7 @@ rcar_dmac_chan_prep_sg(struct rcar_dmac_
 static int rcar_dmac_alloc_chan_resources(struct dma_chan *chan)
 {
struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan);
+   struct rcar_dmac *dmac = to_rcar_dmac(chan->device);
int ret;
 
INIT_LIST_HEAD(&rchan->desc.chunks_free);
@@ -979,7 +997,11 @@ static int rcar_dmac_alloc_chan_resource
if (ret < 0)
return -ENOMEM;
 
-   return pm_runtime_get_sync(chan->device->dev);
+   ret = pm_runtime_get_sync(chan->device->dev);
+   if (!ret)
+   set_bit(rcar_dmac_chan_to_bit(chan), dmac->ch_in_use);
+
+   return ret;
 }
 
 static void rcar_dmac_free_chan_resources(struct dma_chan *chan)
@@ -1028,6 +1050,8 @@ static void rcar_dmac_free_chan_resource
}
 
pm_runtime_put(chan->device->dev);
+
+   clear_bit(rcar_dmac_chan_to_bit(chan), dmac->ch_in_use);
 }
 
 static struct dma_async_tx_descriptor *
@@ -1196,7 +1220,6 @@ static int rcar_dmac_device_config(struc
rchan->dst.slave_addr = cfg->dst_addr;
rchan->src.xfer_size = cfg->src_addr_width;
rchan->dst.xfer_size = cfg->dst_addr_width;
-
return 0;
 }
 
@@ -1540,10 +1563,16 @@ static irqreturn_t rcar_dmac_isr_error(i
  * OF xlate and channel filter
  */
 
+struct rcar_dmac_filter_data {
+   struct of_phandle_args *dma_spec;
+   unsigned int bit_start;
+};
+
 static bool rcar_dmac_chan_filter(struct dma_chan *chan, void *arg)
 {
struct rcar_dmac *dmac = to_rcar_dmac(chan->device);
-   struct of_phandle_args *dma_spec = arg;
+   struct rcar_dmac_filter_data *filter_data = arg;
+   struct of_phandle_args *dma_spec = filter_data->dma_spec;
 
/*
 * FIXME: Using a filter on OF platforms is a nonsense. The OF xlate
@@ -1556,15 +1585,28 @@ static bool rcar_dmac_chan_filter(struct
dma_spec->np != chan->device->dev->of_node)
return false;
 
+   /* Force a certain channel in case bit_start is valid */
+   if (filter_data->bit_start != RCAR_DMAC_CHANNELS_MAX) {
+   dev_dbg(chan->device->dev,
+   "filter ch: %d, start: %d, bit %d\n",
+   to_rcar_dmac_chan(chan)->index, filter_data->bit_start,
+   rcar_dmac_chan_to_bit(chan));
+
+   if (filter_data->bit_start != rcar_dmac_chan_to_bit(chan))
+   return false;
+   }
+
return !test_and_set_bit(dma_spec->args[0], dmac->modules);
 }
 
 static struct dma_chan *rcar_dmac_of_xlate(struct of_phandle_args *dma_spec,
   struct of_dma *ofdma)
 {
+   struct rcar_dmac *dmac = ofdma->of_dma_data;
struct rcar_dmac_chan *rchan;
struct dma_chan *chan;
dma_cap_mask_t mask;
+   struct rcar_dmac_filter_data filter_data;
 
if (dma_spec->args_count != 1)
return NULL;
@@ -1573,7 +1615,48 @@ static struct dma_chan *rcar_dmac_of_xla
dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask);
 
-   chan = dma_request_channel(mask, rcar_dmac_cha

[PATCH 3/3] arm64: dts: r8a7795: Use slow mode for TX on SCIF2/DEBUG1

2017-03-13 Thread Magnus Damm
From: Magnus Damm 

Experimental code to enable slow mode on r8a7795 for SCIF2 TX.

Not-Yet-Signed-off-by: Magnus Damm 
---

 arch/arm64/boot/dts/renesas/r8a7795.dtsi |2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- 0001/arch/arm64/boot/dts/renesas/r8a7795.dtsi
+++ work/arch/arm64/boot/dts/renesas/r8a7795.dtsi   2017-03-13 
23:16:41.350607110 +0900
@@ -771,7 +771,7 @@
 <&cpg CPG_CORE R8A7795_CLK_S3D1>,
 <&scif_clk>;
clock-names = "fck", "brg_int", "scif_clk";
-   dmas = <&dmac1 0x13>, <&dmac1 0x12>;
+   dmas = <&dmac1 0xf13>, <&dmac1 0x12>;
dma-names = "tx", "rx";
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
resets = <&cpg 310>;


[PATCH 2/3] dmaengine: rcar-dmac: Slow mode prototype

2017-03-13 Thread Magnus Damm
From: Magnus Damm 

This experimental slow mode support code simply extends the MID/RID value
to allow encoding a 4-bit value in bit 8-11 to specify the SLM bit value.
With this value set the channel associated with the device will be processed
slower by the hardware. The idea is that the slow mode can be used for testing
to force underruns to harden other parts of the system.

Not-Yet-Signed-off-by: Magnus Damm 
---

 drivers/dma/sh/rcar-dmac.c |   13 ++---
 1 file changed, 10 insertions(+), 3 deletions(-)

--- 0002/drivers/dma/sh/rcar-dmac.c
+++ work/drivers/dma/sh/rcar-dmac.c 2017-03-13 23:15:54.170607110 +0900
@@ -171,6 +171,7 @@ struct rcar_dmac_chan {
struct rcar_dmac_chan_slave dst;
struct rcar_dmac_chan_map map;
int mid_rid;
+   unsigned int slm;
 
spinlock_t lock;
 
@@ -374,7 +375,7 @@ static void rcar_dmac_chan_start_xfer(st
rcar_dmac_chan_write(chan, RCAR_DMADPBASE,
 (desc->hwdescs.dma & 0xfff0) |
 RCAR_DMADPBASE_SEL);
-   rcar_dmac_chan_write(chan, RCAR_DMACHCRB,
+   rcar_dmac_chan_write(chan, RCAR_DMACHCRB, chan->slm |
 RCAR_DMACHCRB_DCNT(desc->nchunks - 1) |
 RCAR_DMACHCRB_DRST);
 
@@ -438,6 +439,7 @@ static void rcar_dmac_chan_start_xfer(st
rcar_dmac_chan_write(chan, RCAR_DMATCR,
 chunk->size >> desc->xfer_shift);
 
+   rcar_dmac_chan_write(chan, RCAR_DMACHCRB, chan->slm);
chcr |= RCAR_DMACHCR_DPM_DISABLED | RCAR_DMACHCR_IE;
}
 
@@ -1596,7 +1598,7 @@ static bool rcar_dmac_chan_filter(struct
return false;
}
 
-   return !test_and_set_bit(dma_spec->args[0], dmac->modules);
+   return !test_and_set_bit(dma_spec->args[0] & 0xff, dmac->modules);
 }
 
 static struct dma_chan *rcar_dmac_of_xlate(struct of_phandle_args *dma_spec,
@@ -1661,7 +1663,12 @@ static struct dma_chan *rcar_dmac_of_xla
return NULL;
 
rchan = to_rcar_dmac_chan(chan);
-   rchan->mid_rid = dma_spec->args[0];
+   rchan->mid_rid = dma_spec->args[0] & 0xff;
+
+   if (dma_spec->args[0] > 0xff) {
+   rchan->slm = RCAR_DMACHCRB_SLM_CLK(dma_spec->args[0] >> 8);
+   dev_info(chan->device->dev, "slm set to 0x%x\n", rchan->slm);
+   }
 
return chan;
 }


[PATCH v3 3/3] iommu/ipmmu-vmsa: Hook up r8a7796 DT matching code

2017-03-11 Thread Magnus Damm
From: Magnus Damm 

Support the r8a7796 IPMMU by sharing feature flags between
r8a7795 and r8a7796. Also update IOMMU_OF_DECLARE to hook
up the updated compat string.

Signed-off-by: Magnus Damm 
---

 Changes since V2:
 - Updated to include white list suppport

 Changes since V1:
 - None

 drivers/iommu/ipmmu-vmsa.c |   14 ++
 1 file changed, 10 insertions(+), 4 deletions(-)

--- 0024/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-03-12 14:14:32.550607110 +0900
@@ -1058,8 +1058,9 @@ static bool ipmmu_slave_whitelist(struct
return false;
 }
 
-static const struct soc_device_attribute soc_r8a7795[] = {
+static const struct soc_device_attribute soc_rcar_gen3[] = {
{ .soc_id = "r8a7795", },
+   { .soc_id = "r8a7796", },
{ /* sentinel */ }
 };
 
@@ -1082,7 +1083,7 @@ static int ipmmu_of_xlate_dma(struct dev
}
 
/* For R-Car Gen3 use a white list to opt-in slave devices */
-   if (soc_device_match(soc_r8a7795) && !ipmmu_slave_whitelist(dev))
+   if (soc_device_match(soc_rcar_gen3) && !ipmmu_slave_whitelist(dev))
return -ENODEV;
 
return ipmmu_init_platform_device(dev);
@@ -1127,7 +1128,7 @@ static const struct ipmmu_features ipmmu
.twobit_imttbcr_sl0 = false,
 };
 
-static const struct ipmmu_features ipmmu_features_r8a7795 = {
+static const struct ipmmu_features ipmmu_features_rcar_gen3 = {
.use_ns_alias_offset = false,
.has_cache_leaf_nodes = true,
.has_eight_ctx = true,
@@ -1141,7 +1142,10 @@ static const struct of_device_id ipmmu_o
.data = &ipmmu_features_default,
}, {
.compatible = "renesas,ipmmu-r8a7795",
-   .data = &ipmmu_features_r8a7795,
+   .data = &ipmmu_features_rcar_gen3,
+   }, {
+   .compatible = "renesas,ipmmu-r8a7796",
+   .data = &ipmmu_features_rcar_gen3,
}, {
/* Terminator */
},
@@ -1333,6 +1337,8 @@ IOMMU_OF_DECLARE(ipmmu_vmsa_iommu_of, "r
 ipmmu_vmsa_iommu_of_setup);
 IOMMU_OF_DECLARE(ipmmu_r8a7795_iommu_of, "renesas,ipmmu-r8a7795",
 ipmmu_vmsa_iommu_of_setup);
+IOMMU_OF_DECLARE(ipmmu_r8a7796_iommu_of, "renesas,ipmmu-r8a7796",
+ipmmu_vmsa_iommu_of_setup);
 #endif
 
 MODULE_DESCRIPTION("IOMMU API for Renesas VMSA-compatible IPMMU");


[PATCH v3 2/3] iommu/ipmmu-vmsa: Increase maximum micro-TLBS to 48

2017-03-11 Thread Magnus Damm
From: Magnus Damm 

Bump up the maximum numbers of micro-TLBS to 48.

Each IPMMU device instance get micro-TLB assignment via
the "iommus" property in DT. Older SoCs tend to use a
maximum number of 32 micro-TLBs per IPMMU instance however
newer SoCs such as r8a7796 make use of up to 48 micro-TLBs.

At this point no SoC specific handling is done to validate
the maximum number of micro-TLBs, and because of that the
DT information is assumed to be within correct range for
each particular SoC.

If needed in the future SoC specific feature flags can be
added to handle the maximum number of micro-TLBs without
requiring DT changes, however at this point this does not
seem necessary.

Signed-off-by: Magnus Damm 
Reviewed-by: Geert Uytterhoeven 
---

 Changes since V2:
 - Added outer set of () to IMUASID() and IMUCTR() - thanks Ramesh!
 - Added Reviewed-by from Geert - thanks!

 Changes since V1:
 - Added support for the second I/O range at 0x600.

 drivers/iommu/ipmmu-vmsa.c |   10 +++---
 1 file changed, 7 insertions(+), 3 deletions(-)

--- 0020/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-03-12 14:11:23.020607110 +0900
@@ -213,7 +213,9 @@ static void set_archdata(struct device *
 #define IMPMBA(n)  (0x0280 + ((n) * 4))
 #define IMPMBD(n)  (0x02c0 + ((n) * 4))
 
-#define IMUCTR(n)  (0x0300 + ((n) * 16))
+#define IMUCTR(n)  ((n) < 32 ? IMUCTR0(n) : IMUCTR32(n))
+#define IMUCTR0(n) (0x0300 + ((n) * 16))
+#define IMUCTR32(n)(0x0600 + (((n) - 32) * 16))
 #define IMUCTR_FIXADDEN(1 << 31)
 #define IMUCTR_FIXADD_MASK (0xff << 16)
 #define IMUCTR_FIXADD_SHIFT16
@@ -223,7 +225,9 @@ static void set_archdata(struct device *
 #define IMUCTR_FLUSH   (1 << 1)
 #define IMUCTR_MMUEN   (1 << 0)
 
-#define IMUASID(n) (0x0308 + ((n) * 16))
+#define IMUASID(n) ((n) < 32 ? IMUASID0(n) : IMUASID32(n))
+#define IMUASID0(n)(0x0308 + ((n) * 16))
+#define IMUASID32(n)   (0x0608 + (((n) - 32) * 16))
 #define IMUASID_ASID8_MASK (0xff << 8)
 #define IMUASID_ASID8_SHIFT8
 #define IMUASID_ASID0_MASK (0xff << 0)
@@ -1164,7 +1168,7 @@ static int ipmmu_probe(struct platform_d
}
 
mmu->dev = &pdev->dev;
-   mmu->num_utlbs = 32;
+   mmu->num_utlbs = 48;
spin_lock_init(&mmu->lock);
bitmap_zero(mmu->ctx, IPMMU_CTX_MAX);
mmu->features = match->data;


[PATCH v3 0/3] iommu/ipmmu-vmsa: r8a7796 support V3

2017-03-11 Thread Magnus Damm
iommu/ipmmu-vmsa: r8a7796 support V3

[PATCH v3 1/3] iommu/ipmmu-vmsa: Add r8a7796 DT binding
[PATCH v3 2/3] iommu/ipmmu-vmsa: Increase maximum micro-TLBS to 48
[PATCH v3 3/3] iommu/ipmmu-vmsa: Hook up r8a7796 DT matching code

This series adds r8a7796 support to the IPMMU driver. The DT binding
gets updated, maximum number of micro-TLBs are increased and the
driver is adjusted to match on the new DT binding.

Changes since V2:
 - Patch 2/3 updated with an outer set of () - thanks Ramesh!
 - Patch 2/3 updated with Reviewed-by - thanks Geert!
 - Patch 3/3 updated to include white list support

Changes since V1:
 - Patch 1/3 updated with more Acked-by tags
 - Patch 2/3 updated with high I/O register range support

Patch 1/3 is ready for upstream merge and includes the following tags:
Signed-off-by: Magnus Damm 
Acked-by: Laurent Pinchart 
Acked-by: Rob Herring 
Acked-by: Simon Horman 
Acked-by: Geert Uytterhoeven 

Patch 2/3 and 3/3 are quite trivial but have now acked-by so far.

Signed-off-by: Magnus Damm 
---

 Developed on top of v4.11-rc1 with the following series applied:
 [PATCH v7 00/07] iommu/ipmmu-vmsa: IPMMU multi-arch update V7
 [PATCH v3 00/09] iommu/ipmmu-vmsa: r8a7795 support V3

 Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt |1 
 drivers/iommu/ipmmu-vmsa.c |   24 
+++---
 2 files changed, 18 insertions(+), 7 deletions(-)


[PATCH v3 1/3] iommu/ipmmu-vmsa: Add r8a7796 DT binding

2017-03-11 Thread Magnus Damm
From: Magnus Damm 

Update the IPMMU DT binding documentation to include the r8a7796 compat
string for R-Car M3-W.

Signed-off-by: Magnus Damm 
Acked-by: Laurent Pinchart 
Acked-by: Rob Herring 
Acked-by: Simon Horman 
Acked-by: Geert Uytterhoeven 
---

 Changes since V2:
 - None

 Changes since V1:
 - Included in series, added Acked-by from Geert - thanks!

 Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt |1 +
 1 file changed, 1 insertion(+)

--- 0001/Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt
+++ work/Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt 
2017-03-12 14:09:01.920607110 +0900
@@ -16,6 +16,7 @@ Required Properties:
 - "renesas,ipmmu-r8a7793" for the R8A7793 (R-Car M2-N) IPMMU.
 - "renesas,ipmmu-r8a7794" for the R8A7794 (R-Car E2) IPMMU.
 - "renesas,ipmmu-r8a7795" for the R8A7795 (R-Car H3) IPMMU.
+- "renesas,ipmmu-r8a7796" for the R8A7796 (R-Car M3-W) IPMMU.
 - "renesas,ipmmu-vmsa" for generic R-Car Gen2 VMSA-compatible IPMMU.
 
   - reg: Base address and size of the IPMMU registers.


Re: [PATCH v3 02/09] iommu/ipmmu-vmsa: Add optional root device feature

2017-03-08 Thread Magnus Damm
Hi Geert,

On Wed, Mar 8, 2017 at 10:47 PM, Geert Uytterhoeven
 wrote:
> Hi Magnus,
>
> On Wed, Mar 8, 2017 at 12:01 PM, Magnus Damm  wrote:
>> From: Magnus Damm 
>>
>> Add root device handling to the IPMMU driver by allowing certain
>> DT compat strings to enable has_cache_leaf_nodes that in turn will
>> support both root devices with interrupts and leaf devices that
>> face the actual IPMMU consumer devices.
>>
>> Signed-off-by: Magnus Damm 
>
>> --- 0011/drivers/iommu/ipmmu-vmsa.c
>> +++ work/drivers/iommu/ipmmu-vmsa.c 2017-03-08 17:56:51.770607110 +0900
>
>> @@ -216,6 +219,44 @@ static void set_archdata(struct device *
>>  #define IMUASID_ASID0_SHIFT0
>>
>>  /* 
>> -
>> + * Root device handling
>> + */
>> +
>> +static bool ipmmu_is_root(struct ipmmu_vmsa_device *mmu)
>> +{
>> +   if (mmu->features->has_cache_leaf_nodes)
>> +   return mmu->is_leaf ? false : true;
>
> Expressions using the ternary operator are sometimes hard to read.
> In this case, you want negation, so why not use that?
>
> return !mmu->is_leaf;
>
>> +   else
>
> I'd drop the else.

Yeah, your suggestion makes the code easier to read. Will fix.

>> +   return true; /* older IPMMU hardware treated as single root 
>> */
>> +}
>> +
>> +static struct ipmmu_vmsa_device *__ipmmu_find_root(void)
>> +{
>> +   struct ipmmu_vmsa_device *mmu;
>> +   bool found = false;
>
> struct ipmmu_vmsa_device *root = NULL;

I used to have it initialized to NULL and not use any found variable
and only return the variable. But then I ran into the error case when
devices exist on the ipmmu_devices list however none of them are root.
I returned the last one on the list regardless if they were root or
not. So I updated the code to use the found variable, and because of
that I thought I could simply drop the NULL assignment.

>> +
>> +   spin_lock(&ipmmu_devices_lock);
>> +
>> +   list_for_each_entry(mmu, &ipmmu_devices, list) {
>> +   if (ipmmu_is_root(mmu)) {
>> +   found = true;
>
> root = mmu;
>
>> +   break;
>> +   }
>> +   }
>> +
>> +   spin_unlock(&ipmmu_devices_lock);
>> +   return found ? mmu : NULL;
>
> return root;

I agree it makes sense to use root as variable name, will fix. Not
sure about the NULL assignment though, can you enlighten me?

Cheers,

/ magnus


Re: [PATCH v3 01/09] iommu/ipmmu-vmsa: Introduce features, break out alias

2017-03-08 Thread Magnus Damm
Hi Robin,

On Wed, Mar 8, 2017 at 8:53 PM, Robin Murphy  wrote:
> Hi Magnus,
>
> On 08/03/17 11:01, Magnus Damm wrote:
>> From: Magnus Damm 
>>
>> Introduce struct ipmmu_features to track various hardware
>> and software implementation changes inside the driver for
>> different kinds of IPMMU hardware. Add use_ns_alias_offset
>> as a first example of a feature to control if the secure
>> register bank offset should be used or not.
>>
>> Signed-off-by: Magnus Damm 
>> ---
>>
>>  Changes since V2:
>>  - None
>>
>>  Changes since V1:
>>  - Moved patch to front of the series
>>
>>  drivers/iommu/ipmmu-vmsa.c |   35 ---
>>  1 file changed, 28 insertions(+), 7 deletions(-)
>>
>> --- 0007/drivers/iommu/ipmmu-vmsa.c
>> +++ work/drivers/iommu/ipmmu-vmsa.c   2017-03-07 12:25:47.0 +0900
>> @@ -32,11 +32,15 @@
>>
>>  #define IPMMU_CTX_MAX 1
>>
>> +struct ipmmu_features {
>> + bool use_ns_alias_offset;
>> +};
>> +
>>  struct ipmmu_vmsa_device {
>>   struct device *dev;
>>   void __iomem *base;
>>   struct list_head list;
>> -
>> + const struct ipmmu_features *features;
>>   unsigned int num_utlbs;
>>   spinlock_t lock;/* Protects ctx and domains[] 
>> */
>>   DECLARE_BITMAP(ctx, IPMMU_CTX_MAX);
>> @@ -999,13 +1003,33 @@ static void ipmmu_device_reset(struct ip
>>   ipmmu_write(mmu, i * IM_CTX_SIZE + IMCTR, 0);
>>  }
>>
>> +static const struct ipmmu_features ipmmu_features_default = {
>> + .use_ns_alias_offset = true,
>> +};
>> +
>> +static const struct of_device_id ipmmu_of_ids[] = {
>> + {
>> + .compatible = "renesas,ipmmu-vmsa",
>> + .data = &ipmmu_features_default,
>> + }, {
>> + /* Terminator */
>> + },
>> +};
>> +
>> +MODULE_DEVICE_TABLE(of, ipmmu_of_ids);
>> +
>>  static int ipmmu_probe(struct platform_device *pdev)
>>  {
>>   struct ipmmu_vmsa_device *mmu;
>> + const struct of_device_id *match;
>>   struct resource *res;
>>   int irq;
>>   int ret;
>>
>> + match = of_match_node(ipmmu_of_ids, pdev->dev.of_node);
>
> of_device_get_match_data() makes this a lot easier.
>
>> + if (!match)
>> + return -EINVAL;
>
> Also, if the driver is DT-only per the other series, note that this
> cannot happen anyway, since of_driver_match_device() would have to have
> found a match for your probe function to be called in the first place.

Yeah, you are right. As you know, in the IPMMU driver (with the
r8a7795 V3 series applied) the init handling is a bit special with
ARM32 and ARM64 being treated differently. I would like to clean it up
and share a common implementation.

Until that happens, how do you think we should handle the (!match)
case? BUG_ON()?

Cheers,

/ magnus


Re: [PATCH v3 09/09] iommu/ipmmu-vmsa: Hook up r8a7795 DT matching code

2017-03-08 Thread Magnus Damm
Hi Geert,

On Wed, Mar 8, 2017 at 10:58 PM, Geert Uytterhoeven
 wrote:
> Hi Magnus,
>
> On Wed, Mar 8, 2017 at 12:02 PM, Magnus Damm  wrote:
>> From: Magnus Damm 
>>
>> Tie in r8a7795 features and update the IOMMU_OF_DECLARE
>> compat string to include the updated compat string.
>>
>> TODO:
>>  - Consider making use of iommu_fwspec_add_ids() for uTLB handling
>>  Needed to coexist with non-OF R-Car Gen2 somehow...
>>  - Break out stuff useful for R-Car Gen2 from this series
>>  Fix up the Gen2 IPMMU support code
>>and/or
>>  Fold more stuff into the multi-arch series
>>  - Add support for sysfs and iommu_device_link()/unlink()
>>
>> Signed-off-by: Magnus Damm 
>
>> --- 0018/drivers/iommu/ipmmu-vmsa.c
>> +++ work/drivers/iommu/ipmmu-vmsa.c 2017-03-08 19:11:53.600607110 +0900
>
>> @@ -1043,6 +1048,17 @@ static struct iommu_group *ipmmu_find_gr
>> return group;
>>  }
>>
>> +static bool ipmmu_slave_whitelist(struct device *dev)
>> +{
>> +   /* By default, do not allow use of IPMMU */
>> +   return false;
>> +}
>> +
>> +static const struct soc_device_attribute soc_r8a7795[] = {
>> +   { .soc_id = "r8a7795", },
>
> If/when the whitelist is/becomes device/revision specific, you probably want
> to store a  pointer to the *_slave_whitelist() function in the .data member?

Yeah, for sure. It is a bit early to tell exactly how the code will
look like at this point, but I think it will become more clear in the
future. Just want to send out a new version of r8a7796 IPMMU support
and some r8a7795 DT integration to get a coherent working set of patch
series out of the door first.

>> +   { /* sentinel */ }
>> +};
>> +
>>  static int ipmmu_of_xlate_dma(struct device *dev,
>>   struct of_phandle_args *spec)
>>  {
>> @@ -1053,6 +1069,18 @@ static int ipmmu_of_xlate_dma(struct dev
>> if (!of_device_is_available(spec->np))
>> return -ENODEV;
>>
>> +   /* Failing in ->attach_device() results in a hang, so make
>> +* sure the root device is installed before going there
>> +*/
>> +   if (!__ipmmu_find_root()) {
>> +   dev_info(dev, "Unable to locate IPMMU root device\n");
>
> dev_err?

Good idea. Will fix.

>> +   return -ENODEV;
>> +   }
>> +
>> +   /* For R-Car Gen3 use a white list to opt-in slave devices */
>> +   if (soc_device_match(soc_r8a7795) && !ipmmu_slave_whitelist(dev))
>> +   return -ENODEV;

This will have to be updated for r8a7796 somehow as well.

Thanks for your help!

Cheers,

/ magnus


Re: [PATCH v3 03/09] iommu/ipmmu-vmsa: Enable multi context support

2017-03-08 Thread Magnus Damm
Hi Robin,

Thanks for your feedback!

On Wed, Mar 8, 2017 at 9:21 PM, Robin Murphy  wrote:
> On 08/03/17 11:01, Magnus Damm wrote:
>> From: Magnus Damm 
>>
>> Add support for up to 8 contexts. Each context is mapped to one
>> domain. One domain is assigned one or more slave devices. Contexts
>> are allocated dynamically and slave devices are grouped together
>> based on which IPMMU device they are connected to. This makes slave
>> devices tied to the same IPMMU device share the same IOVA space.
>>
>> Signed-off-by: Magnus Damm 
>> ---
>>
>>  Changes since V2:
>>  - Updated patch description to reflect code included in:
>>[PATCH v7 00/07] iommu/ipmmu-vmsa: IPMMU multi-arch update V7
>>
>>  Changes since V1:
>>  - Support up to 8 contexts instead of 4
>>  - Use feature flag and runtime handling
>>  - Default to single context
>>
>>  drivers/iommu/ipmmu-vmsa.c |   38 ++
>>  1 file changed, 30 insertions(+), 8 deletions(-)
>>
>> --- 0012/drivers/iommu/ipmmu-vmsa.c
>> +++ work/drivers/iommu/ipmmu-vmsa.c   2017-03-08 17:59:19.900607110 +0900
>> @@ -30,11 +30,12 @@
>>
>>  #include "io-pgtable.h"
>>
>> -#define IPMMU_CTX_MAX 1
>> +#define IPMMU_CTX_MAX 8
>>
>>  struct ipmmu_features {
>>   bool use_ns_alias_offset;
>>   bool has_cache_leaf_nodes;
>> + bool has_eight_ctx;
>
> Wouldn't it be more sensible to just encode a number of contexts
> directly, if it isn't reported by the hardware itself? I'm just
> imagining future hardware generations... :P
>
> bool also_has_another_eight_ctx_on_top_of_that;
> bool wait_no_this_is_the_one_where_ctx_15_isnt_usable;

=)

Sure, I agree with you!

Please note that this is currently a mix of software and hardware
policy. On R-Car Gen2 (ARM32) the legacy code only uses a single
context for now but 4 contexts are supported by hardware according to
the data sheet. The remaining 3 contexts are untested at this point.
For R-Car Gen3 (ARM64) the hardware supports 8 contexts and this patch
enables all of them.

>>  };
>>
>>  struct ipmmu_vmsa_device {
>> @@ -44,6 +45,7 @@ struct ipmmu_vmsa_device {
>>   const struct ipmmu_features *features;
>>   bool is_leaf;
>>   unsigned int num_utlbs;
>> + unsigned int num_ctx;
>>   spinlock_t lock;/* Protects ctx and domains[] 
>> */
>>   DECLARE_BITMAP(ctx, IPMMU_CTX_MAX);
>>   struct ipmmu_vmsa_domain *domains[IPMMU_CTX_MAX];
>> @@ -376,11 +378,12 @@ static int ipmmu_domain_allocate_context
>>
>>   spin_lock_irqsave(&mmu->lock, flags);
>>
>> - ret = find_first_zero_bit(mmu->ctx, IPMMU_CTX_MAX);
>> - if (ret != IPMMU_CTX_MAX) {
>> + ret = find_first_zero_bit(mmu->ctx, mmu->num_ctx);
>> + if (ret != mmu->num_ctx) {
>>   mmu->domains[ret] = domain;
>>   set_bit(ret, mmu->ctx);
>
> Using test_and_set_bit() in a loop would avoid having to take a lock here.

So you mean that in case of test_and_set_bit() returns 1 then we try
find_first_zero_bit() again?

This is not really a performance sensitive part of the driver, so I'm
currently optimizing for code readability. I'm of course all for
dropping the lock, but I have a hard time figuring out how your
suggestion could result in semi-readable code. Any pointers? =)

>> @@ -1112,6 +1123,17 @@ static int ipmmu_probe(struct platform_d
>>   if (mmu->features->use_ns_alias_offset)
>>   mmu->base += IM_NS_ALIAS_OFFSET;
>>
>> + /*
>> +  * The number of contexts varies with generation and instance.
>> +  * Newer SoCs get a total of 8 contexts enabled, older ones just one.
>> +  */
>> + if (mmu->features->has_eight_ctx)
>> + mmu->num_ctx = 8;
>> + else
>> + mmu->num_ctx = 1;
>> +
>> + WARN_ON(mmu->num_ctx > IPMMU_CTX_MAX);
>
> The likelihood of that happening doesn't appear to warrant a runtime
> check. Especially one which probably isn't even generated because it's
> trivially resolvable to "if (false)..." at compile time.

Sure, I agree. Will drop.

Thanks,

/ magnus


Re: [PATCH v3 06/09] iommu/ipmmu-vmsa: Write IMCTR twice

2017-03-08 Thread Magnus Damm
Hi Robin,

On Wed, Mar 8, 2017 at 9:34 PM, Robin Murphy  wrote:
> On 08/03/17 11:02, Magnus Damm wrote:
>> From: Magnus Damm 
>>
>> Write IMCTR both in the root device and the leaf node.
>>
>> Signed-off-by: Magnus Damm 
>> ---
>>
>>  Changes since V2:
>>  - None
>>
>>  Changes since V1:
>>  - None
>>
>>  drivers/iommu/ipmmu-vmsa.c |   17 ++---
>>  1 file changed, 14 insertions(+), 3 deletions(-)
>>
>> --- 0018/drivers/iommu/ipmmu-vmsa.c
>> +++ work/drivers/iommu/ipmmu-vmsa.c   2017-03-08 18:30:36.870607110 +0900
>> @@ -286,6 +286,16 @@ static void ipmmu_ctx_write(struct ipmmu
>>   ipmmu_write(domain->root, domain->context_id * IM_CTX_SIZE + reg, 
>> data);
>>  }
>>
>> +static void ipmmu_ctx_write2(struct ipmmu_vmsa_domain *domain, unsigned int 
>> reg,
>> +  u32 data)
>
> That's pretty cryptic. Maybe both functions could do with less ambiguous
> names - something like ipmmu_ctx_write_root() vs. ipmmu_ctx_write_all(),
> perhaps? (and if there's a more specific hardware term than "all" that
> describes this kind of configuration, even better).

Yeah I agree. Will fix in next version!

Thanks,

/ magnus


Re: [PATCH v3 04/09] iommu/ipmmu-vmsa: Make use of IOMMU_OF_DECLARE()

2017-03-08 Thread Magnus Damm
Hi Geert,

On Wed, Mar 8, 2017 at 10:52 PM, Geert Uytterhoeven
 wrote:
> Hi Magnus,
>
> On Wed, Mar 8, 2017 at 12:02 PM, Magnus Damm  wrote:
>> From: Magnus Damm 
>>
>> Hook up IOMMU_OF_DECLARE() support in case CONFIG_IOMMU_DMA
>> is enabled. The only current supported case for 32-bit ARM
>> is disabled, however for 64-bit ARM usage of OF is required.
>>
>> Signed-off-by: Magnus Damm 
> While I'm not such a big fan of *_OF_DECLARE() (it doesn't support deferred
> probing, which is needed for any device with dependencies, like clocks and
> power domains), what's the rationale for not using IOMMU_OF_DECLARE()
> on arm32, and thus the need for setup_done?

ARM32 could (and should) be converted over to IOMMU_OF_DECLARE(), but
it is just a matter of timing. If we try to do it before ARM32 is
converted over to CONFIG_IOMMU_DMA=y then we have to handle all the
hairy legacy implementation details of IOMMU support in case of
CONFIG_IOMMU_DMA=n _and_ deal with just moving over the init order
bits to OF. Testing and keeping all the combinations working is a lot
of work.

I prefer to kill two birds with one stone and do a larger feature jump
and move over ARM32 to same state of ARM64 (with OF init) once
CONFIG_IOMMU_DMA=y is ready for 32-bit ARM. Just changing the init
order bits to OF while keeping legacy CONFIG_IOMMU_DMA=n code is
introducing potential errors with not much upside. Unless there is
some other reason to do it that I can't see that is. =)

Cheers,

/ magnus


Re: [PATCH v7 06/07] iommu/ipmmu-vmsa: ARM and ARM64 archdata access

2017-03-08 Thread Magnus Damm
Hi Robin,

On Wed, Mar 8, 2017 at 9:48 PM, Robin Murphy  wrote:
> On 07/03/17 03:17, Magnus Damm wrote:
>> From: Magnus Damm 
>>
>> Not all architectures have an iommu member in their archdata, so
>> use #ifdefs support build with COMPILE_TEST on any architecture.
>
> I have a feeling I might be repeating myself, but ipmmu_vmsa_archdata
> looks to be trivially convertible to iommu_fwspec, which I strongly
> encourage, not least because it would obviate bodges like this.

Yeah, I think it should be possible to use iommu_fwspec for this
purpose. The question is when to do it. =)

I actually looked into it recently, but then realised that for this to
work then due to code sharing I need to make use of iommu_fwspec on
both 32-bit and 64-bit ARM. So it requires rework of the existing
IPMMU for 32-bit ARM (including hairy legacy CONFIG_IOMMU_DMA=n code).
I was actually thinking of doing some rework of 32-bit ARM IPMMU code
anyway (I suspect iommu_device_* conversion caused breakage) and it
probably has to happen on top of current -next. I would also like to
start reducing burden of forward porting all these patches, and
stirring up the ground does not really help much there...

Cheers,

/ magnus


[PATCH v3 05/09] iommu/ipmmu-vmsa: IPMMU device is 40-bit bus master

2017-03-08 Thread Magnus Damm
From: Magnus Damm 

The r8a7795 IPMMU supports 40-bit bus mastering. Both
the coherent DMA mask and the streaming DMA mask are
set to unlock the 40-bit address space for coherent
allocations and streaming operations.

Signed-off-by: Magnus Damm 
---

 Changes since V2:
 - Updated the code and commit message to use 40 bits instead of 64 bits

 Changes since V1:
 - Updated the commit message

 drivers/iommu/ipmmu-vmsa.c |1 +
 1 file changed, 1 insertion(+)

--- 0016/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-03-08 18:29:56.390607110 +0900
@@ -1103,6 +1103,7 @@ static int ipmmu_probe(struct platform_d
spin_lock_init(&mmu->lock);
bitmap_zero(mmu->ctx, IPMMU_CTX_MAX);
mmu->features = match->data;
+   dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(40));
 
/* Map I/O memory and request IRQ. */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);


[PATCH v3 04/09] iommu/ipmmu-vmsa: Make use of IOMMU_OF_DECLARE()

2017-03-08 Thread Magnus Damm
From: Magnus Damm 

Hook up IOMMU_OF_DECLARE() support in case CONFIG_IOMMU_DMA
is enabled. The only current supported case for 32-bit ARM
is disabled, however for 64-bit ARM usage of OF is required.

Signed-off-by: Magnus Damm 
---

 Changes since V2:
 - Reworked registration code to make use of recently introduced:
 iommu_device_register()
 iommu_device_set_ops()
 iommu_device_set_fwnode()

 Changes since V1:
 - Reworked slightly to fit updated patch order and
   [PATCH v3 00/06] iommu/ipmmu-vmsa: IPMMU multi-arch update V3

 drivers/iommu/ipmmu-vmsa.c |   39 +++
 1 file changed, 39 insertions(+)

--- 0012/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-03-08 19:08:31.610607110 +0900
@@ -19,6 +19,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -41,6 +42,7 @@ struct ipmmu_features {
 struct ipmmu_vmsa_device {
struct device *dev;
void __iomem *base;
+   struct iommu_device iommu;
struct list_head list;
const struct ipmmu_features *features;
bool is_leaf;
@@ -1161,6 +1163,25 @@ static int ipmmu_probe(struct platform_d
ipmmu_device_reset(mmu);
}
 
+#if defined(CONFIG_IOMMU_DMA)
+   /*
+* Register the IPMMU to the IOMMU subsystem in the following cases:
+* - R-Car Gen2 IPMMU (all devices registered)
+* - R-Car Gen3 IPMMU (leaf devices only - skip root IPMMU-MM device)
+*/
+   if (!mmu->features->has_cache_leaf_nodes || mmu->is_leaf) {
+   ret = iommu_device_register(&mmu->iommu);
+   if (ret)
+   return ret;
+
+   iommu_device_set_ops(&mmu->iommu, &ipmmu_ops);
+   iommu_device_set_fwnode(&mmu->iommu,
+   &pdev->dev.of_node->fwnode);
+
+   if (!iommu_present(&platform_bus_type))
+   bus_set_iommu(&platform_bus_type, &ipmmu_ops);
+   }
+#endif
/*
 * We can't create the ARM mapping here as it requires the bus to have
 * an IOMMU, which only happens when bus_set_iommu() is called in
@@ -1204,15 +1225,22 @@ static struct platform_driver ipmmu_driv
 
 static int __init ipmmu_init(void)
 {
+   static bool setup_done;
int ret;
 
+   if (setup_done)
+   return 0;
+
ret = platform_driver_register(&ipmmu_driver);
if (ret < 0)
return ret;
 
+#if defined(CONFIG_ARM) && !defined(CONFIG_IOMMU_DMA)
if (!iommu_present(&platform_bus_type))
bus_set_iommu(&platform_bus_type, &ipmmu_ops);
+#endif
 
+   setup_done = true;
return 0;
 }
 
@@ -1224,6 +1252,17 @@ static void __exit ipmmu_exit(void)
 subsys_initcall(ipmmu_init);
 module_exit(ipmmu_exit);
 
+#ifdef CONFIG_IOMMU_DMA
+static int __init ipmmu_vmsa_iommu_of_setup(struct device_node *np)
+{
+   ipmmu_init();
+   return 0;
+}
+
+IOMMU_OF_DECLARE(ipmmu_vmsa_iommu_of, "renesas,ipmmu-vmsa",
+ipmmu_vmsa_iommu_of_setup);
+#endif
+
 MODULE_DESCRIPTION("IOMMU API for Renesas VMSA-compatible IPMMU");
 MODULE_AUTHOR("Laurent Pinchart ");
 MODULE_LICENSE("GPL v2");


[PATCH v3 06/09] iommu/ipmmu-vmsa: Write IMCTR twice

2017-03-08 Thread Magnus Damm
From: Magnus Damm 

Write IMCTR both in the root device and the leaf node.

Signed-off-by: Magnus Damm 
---

 Changes since V2:
 - None

 Changes since V1:
 - None

 drivers/iommu/ipmmu-vmsa.c |   17 ++---
 1 file changed, 14 insertions(+), 3 deletions(-)

--- 0018/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-03-08 18:30:36.870607110 +0900
@@ -286,6 +286,16 @@ static void ipmmu_ctx_write(struct ipmmu
ipmmu_write(domain->root, domain->context_id * IM_CTX_SIZE + reg, data);
 }
 
+static void ipmmu_ctx_write2(struct ipmmu_vmsa_domain *domain, unsigned int 
reg,
+u32 data)
+{
+   if (domain->mmu != domain->root)
+   ipmmu_write(domain->mmu,
+   domain->context_id * IM_CTX_SIZE + reg, data);
+
+   ipmmu_write(domain->root, domain->context_id * IM_CTX_SIZE + reg, data);
+}
+
 /* 
-
  * TLB and microTLB Management
  */
@@ -312,7 +322,7 @@ static void ipmmu_tlb_invalidate(struct
 
reg = ipmmu_ctx_read(domain, IMCTR);
reg |= IMCTR_FLUSH;
-   ipmmu_ctx_write(domain, IMCTR, reg);
+   ipmmu_ctx_write2(domain, IMCTR, reg);
 
ipmmu_tlb_sync(domain);
 }
@@ -472,7 +482,8 @@ static int ipmmu_domain_init_context(str
 * software management as we have no use for it. Flush the TLB as
 * required when modifying the context registers.
 */
-   ipmmu_ctx_write(domain, IMCTR, IMCTR_INTEN | IMCTR_FLUSH | IMCTR_MMUEN);
+   ipmmu_ctx_write2(domain, IMCTR,
+IMCTR_INTEN | IMCTR_FLUSH | IMCTR_MMUEN);
 
return 0;
 }
@@ -498,7 +509,7 @@ static void ipmmu_domain_destroy_context
 *
 * TODO: Is TLB flush really needed ?
 */
-   ipmmu_ctx_write(domain, IMCTR, IMCTR_FLUSH);
+   ipmmu_ctx_write2(domain, IMCTR, IMCTR_FLUSH);
ipmmu_tlb_sync(domain);
ipmmu_domain_free_context(domain->root, domain->context_id);
 }


[PATCH v3 03/09] iommu/ipmmu-vmsa: Enable multi context support

2017-03-08 Thread Magnus Damm
From: Magnus Damm 

Add support for up to 8 contexts. Each context is mapped to one
domain. One domain is assigned one or more slave devices. Contexts
are allocated dynamically and slave devices are grouped together
based on which IPMMU device they are connected to. This makes slave
devices tied to the same IPMMU device share the same IOVA space.

Signed-off-by: Magnus Damm 
---

 Changes since V2:
 - Updated patch description to reflect code included in:
   [PATCH v7 00/07] iommu/ipmmu-vmsa: IPMMU multi-arch update V7

 Changes since V1:
 - Support up to 8 contexts instead of 4
 - Use feature flag and runtime handling
 - Default to single context

 drivers/iommu/ipmmu-vmsa.c |   38 ++
 1 file changed, 30 insertions(+), 8 deletions(-)

--- 0012/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-03-08 17:59:19.900607110 +0900
@@ -30,11 +30,12 @@
 
 #include "io-pgtable.h"
 
-#define IPMMU_CTX_MAX 1
+#define IPMMU_CTX_MAX 8
 
 struct ipmmu_features {
bool use_ns_alias_offset;
bool has_cache_leaf_nodes;
+   bool has_eight_ctx;
 };
 
 struct ipmmu_vmsa_device {
@@ -44,6 +45,7 @@ struct ipmmu_vmsa_device {
const struct ipmmu_features *features;
bool is_leaf;
unsigned int num_utlbs;
+   unsigned int num_ctx;
spinlock_t lock;/* Protects ctx and domains[] */
DECLARE_BITMAP(ctx, IPMMU_CTX_MAX);
struct ipmmu_vmsa_domain *domains[IPMMU_CTX_MAX];
@@ -376,11 +378,12 @@ static int ipmmu_domain_allocate_context
 
spin_lock_irqsave(&mmu->lock, flags);
 
-   ret = find_first_zero_bit(mmu->ctx, IPMMU_CTX_MAX);
-   if (ret != IPMMU_CTX_MAX) {
+   ret = find_first_zero_bit(mmu->ctx, mmu->num_ctx);
+   if (ret != mmu->num_ctx) {
mmu->domains[ret] = domain;
set_bit(ret, mmu->ctx);
-   }
+   } else
+   ret = -EBUSY;
 
spin_unlock_irqrestore(&mmu->lock, flags);
 
@@ -425,9 +428,9 @@ static int ipmmu_domain_init_context(str
 * Find an unused context.
 */
ret = ipmmu_domain_allocate_context(domain->root, domain);
-   if (ret == IPMMU_CTX_MAX) {
+   if (ret < 0) {
free_io_pgtable_ops(domain->iop);
-   return -EBUSY;
+   return ret;
}
 
domain->context_id = ret;
@@ -562,7 +565,7 @@ static irqreturn_t ipmmu_irq(int irq, vo
/*
 * Check interrupts for all active contexts.
 */
-   for (i = 0; i < IPMMU_CTX_MAX; i++) {
+   for (i = 0; i < mmu->num_ctx; i++) {
if (!mmu->domains[i])
continue;
if (ipmmu_domain_irq(mmu->domains[i]) == IRQ_HANDLED)
@@ -632,6 +635,13 @@ static int ipmmu_attach_device(struct io
domain->mmu = mmu;
domain->root = root;
ret = ipmmu_domain_init_context(domain);
+   if (ret < 0) {
+   dev_err(dev, "Unable to initialize IPMMU context\n");
+   domain->mmu = NULL;
+   } else {
+   dev_info(dev, "Using IPMMU context %u\n",
+domain->context_id);
+   }
} else if (domain->mmu != mmu) {
/*
 * Something is wrong, we can't attach two devices using
@@ -1047,13 +1057,14 @@ static void ipmmu_device_reset(struct ip
unsigned int i;
 
/* Disable all contexts. */
-   for (i = 0; i < 4; ++i)
+   for (i = 0; i < mmu->num_ctx; ++i)
ipmmu_write(mmu, i * IM_CTX_SIZE + IMCTR, 0);
 }
 
 static const struct ipmmu_features ipmmu_features_default = {
.use_ns_alias_offset = true,
.has_cache_leaf_nodes = false,
+   .has_eight_ctx = false,
 };
 
 static const struct of_device_id ipmmu_of_ids[] = {
@@ -1112,6 +1123,17 @@ static int ipmmu_probe(struct platform_d
if (mmu->features->use_ns_alias_offset)
mmu->base += IM_NS_ALIAS_OFFSET;
 
+   /*
+* The number of contexts varies with generation and instance.
+* Newer SoCs get a total of 8 contexts enabled, older ones just one.
+*/
+   if (mmu->features->has_eight_ctx)
+   mmu->num_ctx = 8;
+   else
+   mmu->num_ctx = 1;
+
+   WARN_ON(mmu->num_ctx > IPMMU_CTX_MAX);
+
irq = platform_get_irq(pdev, 0);
 
/*


[PATCH v3 08/09] iommu/ipmmu-vmsa: Allow two bit SL0

2017-03-08 Thread Magnus Damm
From: Magnus Damm 

Introduce support for two bit SL0 bitfield in IMTTBCR
by using a separate feature flag.

Signed-off-by: Magnus Damm 
---

 Changes since V2:
 - None

 Changes since V1:
 - None

 drivers/iommu/ipmmu-vmsa.c |   15 ++-
 1 file changed, 14 insertions(+), 1 deletion(-)

--- 0022/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-03-08 18:33:07.630607110 +0900
@@ -38,6 +38,7 @@ struct ipmmu_features {
bool has_cache_leaf_nodes;
bool has_eight_ctx;
bool setup_imbuscr;
+   bool twobit_imttbcr_sl0;
 };
 
 struct ipmmu_vmsa_device {
@@ -163,6 +164,10 @@ static void set_archdata(struct device *
 #define IMTTBCR_TSZ0_MASK  (7 << 0)
 #define IMTTBCR_TSZ0_SHIFT O
 
+#define IMTTBCR_SL0_TWOBIT_LVL_3   (0 << 6)
+#define IMTTBCR_SL0_TWOBIT_LVL_2   (1 << 6)
+#define IMTTBCR_SL0_TWOBIT_LVL_1   (2 << 6)
+
 #define IMBUSCR0x000c
 #define IMBUSCR_DVM(1 << 2)
 #define IMBUSCR_BUSSEL_SYS (0 << 0)
@@ -406,6 +411,7 @@ static int ipmmu_domain_allocate_context
 static int ipmmu_domain_init_context(struct ipmmu_vmsa_domain *domain)
 {
u64 ttbr;
+   u32 tmp;
int ret;
 
/*
@@ -458,9 +464,15 @@ static int ipmmu_domain_init_context(str
 * We use long descriptors with inner-shareable WBWA tables and allocate
 * the whole 32-bit VA space to TTBR0.
 */
+
+   if (domain->root->features->twobit_imttbcr_sl0)
+   tmp = IMTTBCR_SL0_TWOBIT_LVL_1;
+   else
+   tmp = IMTTBCR_SL0_LVL_1;
+
ipmmu_ctx_write(domain, IMTTBCR, IMTTBCR_EAE |
IMTTBCR_SH0_INNER_SHAREABLE | IMTTBCR_ORGN0_WB_WA |
-   IMTTBCR_IRGN0_WB_WA | IMTTBCR_SL0_LVL_1);
+   IMTTBCR_IRGN0_WB_WA | tmp);
 
/* MAIR0 */
ipmmu_ctx_write(domain, IMMAIR0, domain->cfg.arm_lpae_s1_cfg.mair[0]);
@@ -1080,6 +1092,7 @@ static const struct ipmmu_features ipmmu
.has_cache_leaf_nodes = false,
.has_eight_ctx = false,
.setup_imbuscr = true,
+   .twobit_imttbcr_sl0 = false,
 };
 
 static const struct of_device_id ipmmu_of_ids[] = {


[PATCH v3 09/09] iommu/ipmmu-vmsa: Hook up r8a7795 DT matching code

2017-03-08 Thread Magnus Damm
From: Magnus Damm 

Tie in r8a7795 features and update the IOMMU_OF_DECLARE
compat string to include the updated compat string.

TODO:
 - Consider making use of iommu_fwspec_add_ids() for uTLB handling
 Needed to coexist with non-OF R-Car Gen2 somehow...
 - Break out stuff useful for R-Car Gen2 from this series
 Fix up the Gen2 IPMMU support code
   and/or
 Fold more stuff into the multi-arch series
 - Add support for sysfs and iommu_device_link()/unlink()

Signed-off-by: Magnus Damm 
---

 Changes since V2:
 - Check for lack of root device in ->xlate()
   This fixed a bug when IPMMU-MM is disabled in DT the system hangs on boot
 - Added code to ipmmu_init_platform_device() to handle multiple ->xlate() calls
 - Include empty white list by default
 - Updated TODO list

 Changes since V1:
 - Enable multi context feature
 - Update TODO list

 drivers/iommu/ipmmu-vmsa.c |   41 +
 1 file changed, 41 insertions(+)

--- 0018/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-03-08 19:11:53.600607110 +0900
@@ -23,6 +23,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #if defined(CONFIG_ARM) && !defined(CONFIG_IOMMU_DMA)
 #include 
@@ -770,6 +771,10 @@ static int ipmmu_init_platform_device(st
int num_utlbs;
int ret = -ENODEV;
 
+   /* Initialize once - xlate() will call multiple times */
+   if (to_archdata(dev))
+   return 0;
+
/* Find the master corresponding to the device. */
 
num_utlbs = of_count_phandle_with_args(dev->of_node, "iommus",
@@ -1043,6 +1048,17 @@ static struct iommu_group *ipmmu_find_gr
return group;
 }
 
+static bool ipmmu_slave_whitelist(struct device *dev)
+{
+   /* By default, do not allow use of IPMMU */
+   return false;
+}
+
+static const struct soc_device_attribute soc_r8a7795[] = {
+   { .soc_id = "r8a7795", },
+   { /* sentinel */ }
+};
+
 static int ipmmu_of_xlate_dma(struct device *dev,
  struct of_phandle_args *spec)
 {
@@ -1053,6 +1069,18 @@ static int ipmmu_of_xlate_dma(struct dev
if (!of_device_is_available(spec->np))
return -ENODEV;
 
+   /* Failing in ->attach_device() results in a hang, so make
+* sure the root device is installed before going there
+*/
+   if (!__ipmmu_find_root()) {
+   dev_info(dev, "Unable to locate IPMMU root device\n");
+   return -ENODEV;
+   }
+
+   /* For R-Car Gen3 use a white list to opt-in slave devices */
+   if (soc_device_match(soc_r8a7795) && !ipmmu_slave_whitelist(dev))
+   return -ENODEV;
+
return ipmmu_init_platform_device(dev);
 }
 
@@ -1095,11 +1123,22 @@ static const struct ipmmu_features ipmmu
.twobit_imttbcr_sl0 = false,
 };
 
+static const struct ipmmu_features ipmmu_features_r8a7795 = {
+   .use_ns_alias_offset = false,
+   .has_cache_leaf_nodes = true,
+   .has_eight_ctx = true,
+   .setup_imbuscr = false,
+   .twobit_imttbcr_sl0 = true,
+};
+
 static const struct of_device_id ipmmu_of_ids[] = {
{
.compatible = "renesas,ipmmu-vmsa",
.data = &ipmmu_features_default,
}, {
+   .compatible = "renesas,ipmmu-r8a7795",
+   .data = &ipmmu_features_r8a7795,
+   }, {
/* Terminator */
},
 };
@@ -1288,6 +1327,8 @@ static int __init ipmmu_vmsa_iommu_of_se
 
 IOMMU_OF_DECLARE(ipmmu_vmsa_iommu_of, "renesas,ipmmu-vmsa",
 ipmmu_vmsa_iommu_of_setup);
+IOMMU_OF_DECLARE(ipmmu_r8a7795_iommu_of, "renesas,ipmmu-r8a7795",
+ipmmu_vmsa_iommu_of_setup);
 #endif
 
 MODULE_DESCRIPTION("IOMMU API for Renesas VMSA-compatible IPMMU");


[PATCH v3 07/09] iommu/ipmmu-vmsa: Make IMBUSCTR setup optional

2017-03-08 Thread Magnus Damm
From: Magnus Damm 

Introduce a feature to allow opt-out of setting up
IMBUSCR. The default case is unchanged.

Signed-off-by: Magnus Damm 
---

 Changes since V2:
 - None

 Changes since V1:
 - Updated the commit message
 - Reworked patch to coexist with the multi context feature

 drivers/iommu/ipmmu-vmsa.c |   10 ++
 1 file changed, 6 insertions(+), 4 deletions(-)

--- 0020/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-03-08 18:32:26.280607110 +0900
@@ -37,6 +37,7 @@ struct ipmmu_features {
bool use_ns_alias_offset;
bool has_cache_leaf_nodes;
bool has_eight_ctx;
+   bool setup_imbuscr;
 };
 
 struct ipmmu_vmsa_device {
@@ -465,10 +466,10 @@ static int ipmmu_domain_init_context(str
ipmmu_ctx_write(domain, IMMAIR0, domain->cfg.arm_lpae_s1_cfg.mair[0]);
 
/* IMBUSCR */
-   ipmmu_ctx_write(domain, IMBUSCR,
-   ipmmu_ctx_read(domain, IMBUSCR) &
-   ~(IMBUSCR_DVM | IMBUSCR_BUSSEL_MASK));
-
+   if (domain->root->features->setup_imbuscr)
+   ipmmu_ctx_write(domain, IMBUSCR,
+   ipmmu_ctx_read(domain, IMBUSCR) &
+   ~(IMBUSCR_DVM | IMBUSCR_BUSSEL_MASK));
/*
 * IMSTR
 * Clear all interrupt flags.
@@ -1078,6 +1079,7 @@ static const struct ipmmu_features ipmmu
.use_ns_alias_offset = true,
.has_cache_leaf_nodes = false,
.has_eight_ctx = false,
+   .setup_imbuscr = true,
 };
 
 static const struct of_device_id ipmmu_of_ids[] = {


[PATCH v3 02/09] iommu/ipmmu-vmsa: Add optional root device feature

2017-03-08 Thread Magnus Damm
From: Magnus Damm 

Add root device handling to the IPMMU driver by allowing certain
DT compat strings to enable has_cache_leaf_nodes that in turn will
support both root devices with interrupts and leaf devices that
face the actual IPMMU consumer devices.

Signed-off-by: Magnus Damm 
---

 Changes since V2:
 - Fixed a bug in ipmmu_find_root() when only leaf devices are present
 - Broke out __ipmmu_find_root() to allow ->xlate() check for root devices

 Changes since V1:
 - Moved patch to earlier in the series
 - Updated code to work with recent changes in:
   [PATCH v3 00/06] iommu/ipmmu-vmsa: IPMMU multi-arch update V3

 drivers/iommu/ipmmu-vmsa.c |   95 
 1 file changed, 78 insertions(+), 17 deletions(-)

--- 0011/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-03-08 17:56:51.770607110 +0900
@@ -34,6 +34,7 @@
 
 struct ipmmu_features {
bool use_ns_alias_offset;
+   bool has_cache_leaf_nodes;
 };
 
 struct ipmmu_vmsa_device {
@@ -41,6 +42,7 @@ struct ipmmu_vmsa_device {
void __iomem *base;
struct list_head list;
const struct ipmmu_features *features;
+   bool is_leaf;
unsigned int num_utlbs;
spinlock_t lock;/* Protects ctx and domains[] */
DECLARE_BITMAP(ctx, IPMMU_CTX_MAX);
@@ -51,6 +53,7 @@ struct ipmmu_vmsa_device {
 
 struct ipmmu_vmsa_domain {
struct ipmmu_vmsa_device *mmu;
+   struct ipmmu_vmsa_device *root;
struct iommu_domain io_domain;
 
struct io_pgtable_cfg cfg;
@@ -216,6 +219,44 @@ static void set_archdata(struct device *
 #define IMUASID_ASID0_SHIFT0
 
 /* 
-
+ * Root device handling
+ */
+
+static bool ipmmu_is_root(struct ipmmu_vmsa_device *mmu)
+{
+   if (mmu->features->has_cache_leaf_nodes)
+   return mmu->is_leaf ? false : true;
+   else
+   return true; /* older IPMMU hardware treated as single root */
+}
+
+static struct ipmmu_vmsa_device *__ipmmu_find_root(void)
+{
+   struct ipmmu_vmsa_device *mmu;
+   bool found = false;
+
+   spin_lock(&ipmmu_devices_lock);
+
+   list_for_each_entry(mmu, &ipmmu_devices, list) {
+   if (ipmmu_is_root(mmu)) {
+   found = true;
+   break;
+   }
+   }
+
+   spin_unlock(&ipmmu_devices_lock);
+   return found ? mmu : NULL;
+}
+
+static struct ipmmu_vmsa_device *ipmmu_find_root(struct ipmmu_vmsa_device 
*leaf)
+{
+   if (ipmmu_is_root(leaf))
+   return leaf;
+   else
+   return __ipmmu_find_root();
+}
+
+/* 
-
  * Read/Write Access
  */
 
@@ -232,13 +273,13 @@ static void ipmmu_write(struct ipmmu_vms
 
 static u32 ipmmu_ctx_read(struct ipmmu_vmsa_domain *domain, unsigned int reg)
 {
-   return ipmmu_read(domain->mmu, domain->context_id * IM_CTX_SIZE + reg);
+   return ipmmu_read(domain->root, domain->context_id * IM_CTX_SIZE + reg);
 }
 
 static void ipmmu_ctx_write(struct ipmmu_vmsa_domain *domain, unsigned int reg,
u32 data)
 {
-   ipmmu_write(domain->mmu, domain->context_id * IM_CTX_SIZE + reg, data);
+   ipmmu_write(domain->root, domain->context_id * IM_CTX_SIZE + reg, data);
 }
 
 /* 
-
@@ -373,7 +414,7 @@ static int ipmmu_domain_init_context(str
 * TODO: Add support for coherent walk through CCI with DVM and remove
 * cache handling. For now, delegate it to the io-pgtable code.
 */
-   domain->cfg.iommu_dev = domain->mmu->dev;
+   domain->cfg.iommu_dev = domain->root->dev;
 
domain->iop = alloc_io_pgtable_ops(ARM_32_LPAE_S1, &domain->cfg,
   domain);
@@ -383,7 +424,7 @@ static int ipmmu_domain_init_context(str
/*
 * Find an unused context.
 */
-   ret = ipmmu_domain_allocate_context(domain->mmu, domain);
+   ret = ipmmu_domain_allocate_context(domain->root, domain);
if (ret == IPMMU_CTX_MAX) {
free_io_pgtable_ops(domain->iop);
return -EBUSY;
@@ -454,7 +495,7 @@ static void ipmmu_domain_destroy_context
 */
ipmmu_ctx_write(domain, IMCTR, IMCTR_FLUSH);
ipmmu_tlb_sync(domain);
-   ipmmu_domain_free_context(domain->mmu, domain->context_id);
+   ipmmu_domain_free_context(domain->root, domain->context_id);
 }
 
 /* 
-
@@ -567,7 +608,7 @@ static int ipmmu_attach_device(struct io
   struct device *dev)
 {
struct ipmmu_vmsa_archdata *archdata = to_archdata(de

[PATCH v3 01/09] iommu/ipmmu-vmsa: Introduce features, break out alias

2017-03-08 Thread Magnus Damm
From: Magnus Damm 

Introduce struct ipmmu_features to track various hardware
and software implementation changes inside the driver for
different kinds of IPMMU hardware. Add use_ns_alias_offset
as a first example of a feature to control if the secure
register bank offset should be used or not.

Signed-off-by: Magnus Damm 
---

 Changes since V2:
 - None

 Changes since V1:
 - Moved patch to front of the series

 drivers/iommu/ipmmu-vmsa.c |   35 ---
 1 file changed, 28 insertions(+), 7 deletions(-)

--- 0007/drivers/iommu/ipmmu-vmsa.c
+++ work/drivers/iommu/ipmmu-vmsa.c 2017-03-07 12:25:47.0 +0900
@@ -32,11 +32,15 @@
 
 #define IPMMU_CTX_MAX 1
 
+struct ipmmu_features {
+   bool use_ns_alias_offset;
+};
+
 struct ipmmu_vmsa_device {
struct device *dev;
void __iomem *base;
struct list_head list;
-
+   const struct ipmmu_features *features;
unsigned int num_utlbs;
spinlock_t lock;/* Protects ctx and domains[] */
DECLARE_BITMAP(ctx, IPMMU_CTX_MAX);
@@ -999,13 +1003,33 @@ static void ipmmu_device_reset(struct ip
ipmmu_write(mmu, i * IM_CTX_SIZE + IMCTR, 0);
 }
 
+static const struct ipmmu_features ipmmu_features_default = {
+   .use_ns_alias_offset = true,
+};
+
+static const struct of_device_id ipmmu_of_ids[] = {
+   {
+   .compatible = "renesas,ipmmu-vmsa",
+   .data = &ipmmu_features_default,
+   }, {
+   /* Terminator */
+   },
+};
+
+MODULE_DEVICE_TABLE(of, ipmmu_of_ids);
+
 static int ipmmu_probe(struct platform_device *pdev)
 {
struct ipmmu_vmsa_device *mmu;
+   const struct of_device_id *match;
struct resource *res;
int irq;
int ret;
 
+   match = of_match_node(ipmmu_of_ids, pdev->dev.of_node);
+   if (!match)
+   return -EINVAL;
+
mmu = devm_kzalloc(&pdev->dev, sizeof(*mmu), GFP_KERNEL);
if (!mmu) {
dev_err(&pdev->dev, "cannot allocate device data\n");
@@ -1016,6 +1040,7 @@ static int ipmmu_probe(struct platform_d
mmu->num_utlbs = 32;
spin_lock_init(&mmu->lock);
bitmap_zero(mmu->ctx, IPMMU_CTX_MAX);
+   mmu->features = match->data;
 
/* Map I/O memory and request IRQ. */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -1035,7 +1060,8 @@ static int ipmmu_probe(struct platform_d
 * Offset the registers base unconditionally to point to the non-secure
 * alias space for now.
 */
-   mmu->base += IM_NS_ALIAS_OFFSET;
+   if (mmu->features->use_ns_alias_offset)
+   mmu->base += IM_NS_ALIAS_OFFSET;
 
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
@@ -1084,11 +1110,6 @@ static int ipmmu_remove(struct platform_
return 0;
 }
 
-static const struct of_device_id ipmmu_of_ids[] = {
-   { .compatible = "renesas,ipmmu-vmsa", },
-   { }
-};
-
 static struct platform_driver ipmmu_driver = {
.driver = {
.name = "ipmmu-vmsa",


  1   2   3   4   5   6   7   >