All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v1 0/4] add mailbox support for i.MX7D
@ 2018-06-01  6:58 ` Oleksij Rempel
  0 siblings, 0 replies; 54+ messages in thread
From: Oleksij Rempel @ 2018-06-01  6:58 UTC (permalink / raw)
  To: Shawn Guo, Fabio Estevam, Rob Herring, Mark Rutland
  Cc: Oleksij Rempel, linux-clk, linux-arm-kernel, kernel, devicetree

This patches are providing support for mailbox (Messaging Unit)
for i.MX7D.
Functionality was tested on PHYTEC phyBOARD-Zeta i.MX7D with
Linux running on all cores: ARM Cortex-A7 and ARM Cortex-M4.

Both parts of i.MX messaging Unit are visible for all CPUs available
on i.MX7D. Communication worked independent of MU side in combination
with CPU. For example MU-A used on ARM Cortex-A7 and MU-B used on ARM Cortex-M4
or other ways around.

The question to NXP developers: are there are limitations or
recommendations about MU vs CPU combination? The i.MX7D documentation
talks about "Processor A" and "Processor B". It is not quite clear what
processor it actually is (A7 or M4).

Oleksij Rempel (4):
  clk: imx7d: add IMX7D_MU_ROOT_CLK
  dt-bindings: mailbox: provide imx-mailbox documentation
  ARM: dts: imx7s: add i.MX7 messaging unit support
  mailbox: Add support for i.MX7D messaging unit

 .../bindings/mailbox/imx-mailbox.txt          |  35 +++
 arch/arm/boot/dts/imx7s.dtsi                  |  18 ++
 drivers/clk/imx/clk-imx7d.c                   |   1 +
 drivers/mailbox/Kconfig                       |   6 +
 drivers/mailbox/Makefile                      |   2 +
 drivers/mailbox/imx-mailbox.c                 | 289 ++++++++++++++++++
 6 files changed, 351 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mailbox/imx-mailbox.txt
 create mode 100644 drivers/mailbox/imx-mailbox.c

-- 
2.17.1

^ permalink raw reply	[flat|nested] 54+ messages in thread

* [PATCH v1 0/4] add mailbox support for i.MX7D
@ 2018-06-01  6:58 ` Oleksij Rempel
  0 siblings, 0 replies; 54+ messages in thread
From: Oleksij Rempel @ 2018-06-01  6:58 UTC (permalink / raw)
  To: Shawn Guo, Fabio Estevam, Rob Herring, Mark Rutland
  Cc: Oleksij Rempel, kernel, linux-arm-kernel, devicetree, linux-clk

This patches are providing support for mailbox (Messaging Unit)
for i.MX7D.
Functionality was tested on PHYTEC phyBOARD-Zeta i.MX7D with
Linux running on all cores: ARM Cortex-A7 and ARM Cortex-M4.

Both parts of i.MX messaging Unit are visible for all CPUs available
on i.MX7D. Communication worked independent of MU side in combination
with CPU. For example MU-A used on ARM Cortex-A7 and MU-B used on ARM Cortex-M4
or other ways around.

The question to NXP developers: are there are limitations or
recommendations about MU vs CPU combination? The i.MX7D documentation
talks about "Processor A" and "Processor B". It is not quite clear what
processor it actually is (A7 or M4).

Oleksij Rempel (4):
  clk: imx7d: add IMX7D_MU_ROOT_CLK
  dt-bindings: mailbox: provide imx-mailbox documentation
  ARM: dts: imx7s: add i.MX7 messaging unit support
  mailbox: Add support for i.MX7D messaging unit

 .../bindings/mailbox/imx-mailbox.txt          |  35 +++
 arch/arm/boot/dts/imx7s.dtsi                  |  18 ++
 drivers/clk/imx/clk-imx7d.c                   |   1 +
 drivers/mailbox/Kconfig                       |   6 +
 drivers/mailbox/Makefile                      |   2 +
 drivers/mailbox/imx-mailbox.c                 | 289 ++++++++++++++++++
 6 files changed, 351 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mailbox/imx-mailbox.txt
 create mode 100644 drivers/mailbox/imx-mailbox.c

-- 
2.17.1


^ permalink raw reply	[flat|nested] 54+ messages in thread

* [PATCH v1 0/4] add mailbox support for i.MX7D
@ 2018-06-01  6:58 ` Oleksij Rempel
  0 siblings, 0 replies; 54+ messages in thread
From: Oleksij Rempel @ 2018-06-01  6:58 UTC (permalink / raw)
  To: linux-arm-kernel

This patches are providing support for mailbox (Messaging Unit)
for i.MX7D.
Functionality was tested on PHYTEC phyBOARD-Zeta i.MX7D with
Linux running on all cores: ARM Cortex-A7 and ARM Cortex-M4.

Both parts of i.MX messaging Unit are visible for all CPUs available
on i.MX7D. Communication worked independent of MU side in combination
with CPU. For example MU-A used on ARM Cortex-A7 and MU-B used on ARM Cortex-M4
or other ways around.

The question to NXP developers: are there are limitations or
recommendations about MU vs CPU combination? The i.MX7D documentation
talks about "Processor A" and "Processor B". It is not quite clear what
processor it actually is (A7 or M4).

Oleksij Rempel (4):
  clk: imx7d: add IMX7D_MU_ROOT_CLK
  dt-bindings: mailbox: provide imx-mailbox documentation
  ARM: dts: imx7s: add i.MX7 messaging unit support
  mailbox: Add support for i.MX7D messaging unit

 .../bindings/mailbox/imx-mailbox.txt          |  35 +++
 arch/arm/boot/dts/imx7s.dtsi                  |  18 ++
 drivers/clk/imx/clk-imx7d.c                   |   1 +
 drivers/mailbox/Kconfig                       |   6 +
 drivers/mailbox/Makefile                      |   2 +
 drivers/mailbox/imx-mailbox.c                 | 289 ++++++++++++++++++
 6 files changed, 351 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mailbox/imx-mailbox.txt
 create mode 100644 drivers/mailbox/imx-mailbox.c

-- 
2.17.1

^ permalink raw reply	[flat|nested] 54+ messages in thread

* [PATCH v1 1/4] clk: imx7d: add IMX7D_MU_ROOT_CLK
  2018-06-01  6:58 ` Oleksij Rempel
  (?)
@ 2018-06-01  6:58   ` Oleksij Rempel
  -1 siblings, 0 replies; 54+ messages in thread
From: Oleksij Rempel @ 2018-06-01  6:58 UTC (permalink / raw)
  To: Shawn Guo, Fabio Estevam, Rob Herring, Mark Rutland
  Cc: Oleksij Rempel, linux-clk, linux-arm-kernel, kernel, devicetree

This clock is needed for iMX mailbox driver

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
---
 drivers/clk/imx/clk-imx7d.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/clk/imx/clk-imx7d.c b/drivers/clk/imx/clk-imx7d.c
index 975a20d3cc94..1c2541dc40e7 100644
--- a/drivers/clk/imx/clk-imx7d.c
+++ b/drivers/clk/imx/clk-imx7d.c
@@ -793,6 +793,7 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
 	clks[IMX7D_DRAM_PHYM_ROOT_CLK] = imx_clk_gate4("dram_phym_root_clk", "dram_phym_cg", base + 0x4130, 0);
 	clks[IMX7D_DRAM_PHYM_ALT_ROOT_CLK] = imx_clk_gate4("dram_phym_alt_root_clk", "dram_phym_alt_post_div", base + 0x4130, 0);
 	clks[IMX7D_DRAM_ALT_ROOT_CLK] = imx_clk_gate4("dram_alt_root_clk", "dram_alt_post_div", base + 0x4130, 0);
+	clks[IMX7D_MU_ROOT_CLK] = imx_clk_gate2("mu_root_clk", "ipg_root_clk", base + 0x4270, 0);
 	clks[IMX7D_OCOTP_CLK] = imx_clk_gate4("ocotp_clk", "ipg_root_clk", base + 0x4230, 0);
 	clks[IMX7D_SNVS_CLK] = imx_clk_gate4("snvs_clk", "ipg_root_clk", base + 0x4250, 0);
 	clks[IMX7D_CAAM_CLK] = imx_clk_gate4("caam_clk", "ipg_root_clk", base + 0x4240, 0);
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH v1 1/4] clk: imx7d: add IMX7D_MU_ROOT_CLK
@ 2018-06-01  6:58   ` Oleksij Rempel
  0 siblings, 0 replies; 54+ messages in thread
From: Oleksij Rempel @ 2018-06-01  6:58 UTC (permalink / raw)
  To: Shawn Guo, Fabio Estevam, Rob Herring, Mark Rutland
  Cc: Oleksij Rempel, kernel, linux-arm-kernel, devicetree, linux-clk

This clock is needed for iMX mailbox driver

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
---
 drivers/clk/imx/clk-imx7d.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/clk/imx/clk-imx7d.c b/drivers/clk/imx/clk-imx7d.c
index 975a20d3cc94..1c2541dc40e7 100644
--- a/drivers/clk/imx/clk-imx7d.c
+++ b/drivers/clk/imx/clk-imx7d.c
@@ -793,6 +793,7 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
 	clks[IMX7D_DRAM_PHYM_ROOT_CLK] = imx_clk_gate4("dram_phym_root_clk", "dram_phym_cg", base + 0x4130, 0);
 	clks[IMX7D_DRAM_PHYM_ALT_ROOT_CLK] = imx_clk_gate4("dram_phym_alt_root_clk", "dram_phym_alt_post_div", base + 0x4130, 0);
 	clks[IMX7D_DRAM_ALT_ROOT_CLK] = imx_clk_gate4("dram_alt_root_clk", "dram_alt_post_div", base + 0x4130, 0);
+	clks[IMX7D_MU_ROOT_CLK] = imx_clk_gate2("mu_root_clk", "ipg_root_clk", base + 0x4270, 0);
 	clks[IMX7D_OCOTP_CLK] = imx_clk_gate4("ocotp_clk", "ipg_root_clk", base + 0x4230, 0);
 	clks[IMX7D_SNVS_CLK] = imx_clk_gate4("snvs_clk", "ipg_root_clk", base + 0x4250, 0);
 	clks[IMX7D_CAAM_CLK] = imx_clk_gate4("caam_clk", "ipg_root_clk", base + 0x4240, 0);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH v1 1/4] clk: imx7d: add IMX7D_MU_ROOT_CLK
@ 2018-06-01  6:58   ` Oleksij Rempel
  0 siblings, 0 replies; 54+ messages in thread
From: Oleksij Rempel @ 2018-06-01  6:58 UTC (permalink / raw)
  To: linux-arm-kernel

This clock is needed for iMX mailbox driver

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
---
 drivers/clk/imx/clk-imx7d.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/clk/imx/clk-imx7d.c b/drivers/clk/imx/clk-imx7d.c
index 975a20d3cc94..1c2541dc40e7 100644
--- a/drivers/clk/imx/clk-imx7d.c
+++ b/drivers/clk/imx/clk-imx7d.c
@@ -793,6 +793,7 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
 	clks[IMX7D_DRAM_PHYM_ROOT_CLK] = imx_clk_gate4("dram_phym_root_clk", "dram_phym_cg", base + 0x4130, 0);
 	clks[IMX7D_DRAM_PHYM_ALT_ROOT_CLK] = imx_clk_gate4("dram_phym_alt_root_clk", "dram_phym_alt_post_div", base + 0x4130, 0);
 	clks[IMX7D_DRAM_ALT_ROOT_CLK] = imx_clk_gate4("dram_alt_root_clk", "dram_alt_post_div", base + 0x4130, 0);
+	clks[IMX7D_MU_ROOT_CLK] = imx_clk_gate2("mu_root_clk", "ipg_root_clk", base + 0x4270, 0);
 	clks[IMX7D_OCOTP_CLK] = imx_clk_gate4("ocotp_clk", "ipg_root_clk", base + 0x4230, 0);
 	clks[IMX7D_SNVS_CLK] = imx_clk_gate4("snvs_clk", "ipg_root_clk", base + 0x4250, 0);
 	clks[IMX7D_CAAM_CLK] = imx_clk_gate4("caam_clk", "ipg_root_clk", base + 0x4240, 0);
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH v1 2/4] dt-bindings: mailbox: provide imx-mailbox documentation
  2018-06-01  6:58 ` Oleksij Rempel
  (?)
@ 2018-06-01  6:58   ` Oleksij Rempel
  -1 siblings, 0 replies; 54+ messages in thread
From: Oleksij Rempel @ 2018-06-01  6:58 UTC (permalink / raw)
  To: Shawn Guo, Fabio Estevam, Rob Herring, Mark Rutland
  Cc: Oleksij Rempel, linux-clk, linux-arm-kernel, kernel, devicetree

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
---
 .../bindings/mailbox/imx-mailbox.txt          | 35 +++++++++++++++++++
 1 file changed, 35 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mailbox/imx-mailbox.txt

diff --git a/Documentation/devicetree/bindings/mailbox/imx-mailbox.txt b/Documentation/devicetree/bindings/mailbox/imx-mailbox.txt
new file mode 100644
index 000000000000..a45604b33039
--- /dev/null
+++ b/Documentation/devicetree/bindings/mailbox/imx-mailbox.txt
@@ -0,0 +1,35 @@
+i.MX Messaging Unit
+===================
+
+The i.MX Messaging Unit (MU) contains two register sets: "A" and "B". In most cases
+they are accessible from all Processor Units. On one hand, at least for mailbox functionality,
+it makes no difference which application or processor is using which set of the MU. On
+other hand, the register sets for each of the MU parts are not identical.
+
+Required properties:
+- compatible :	Shell be one of:
+                    "fsl,imx7s-mu-a" and "fsl,imx7s-mu-b" for i.MX7S or i.MX7D
+- reg : 	physical base address of the mailbox and length of
+		memory mapped region.
+- #mbox-cells:	Common mailbox binding property to identify the number
+		of cells required for the mailbox specifier. Should be 1.
+- interrupts :	interrupt number. The interrupt specifier format
+		depends on the interrupt controller parent.
+- clocks     :  phandle to the input clock.
+
+Example:
+	mu0a: mu@30aa0000 {
+		compatible = "fsl,imx7s-mu-a";
+		reg = <0x30aa0000 0x28>;
+		interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&clks IMX7D_MU_ROOT_CLK>;
+		#mbox-cells = <1>;
+	};
+
+	mu0b: mu@30ab0000 {
+		compatible = "fsl,imx7s-mu-b";
+		reg = <0x30ab0000 0x28>;
+		interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&clks IMX7D_MU_ROOT_CLK>;
+		#mbox-cells = <1>;
+	};
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH v1 2/4] dt-bindings: mailbox: provide imx-mailbox documentation
@ 2018-06-01  6:58   ` Oleksij Rempel
  0 siblings, 0 replies; 54+ messages in thread
From: Oleksij Rempel @ 2018-06-01  6:58 UTC (permalink / raw)
  To: Shawn Guo, Fabio Estevam, Rob Herring, Mark Rutland
  Cc: Oleksij Rempel, kernel, linux-arm-kernel, devicetree, linux-clk

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
---
 .../bindings/mailbox/imx-mailbox.txt          | 35 +++++++++++++++++++
 1 file changed, 35 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mailbox/imx-mailbox.txt

diff --git a/Documentation/devicetree/bindings/mailbox/imx-mailbox.txt b/Documentation/devicetree/bindings/mailbox/imx-mailbox.txt
new file mode 100644
index 000000000000..a45604b33039
--- /dev/null
+++ b/Documentation/devicetree/bindings/mailbox/imx-mailbox.txt
@@ -0,0 +1,35 @@
+i.MX Messaging Unit
+===================
+
+The i.MX Messaging Unit (MU) contains two register sets: "A" and "B". In most cases
+they are accessible from all Processor Units. On one hand, at least for mailbox functionality,
+it makes no difference which application or processor is using which set of the MU. On
+other hand, the register sets for each of the MU parts are not identical.
+
+Required properties:
+- compatible :	Shell be one of:
+                    "fsl,imx7s-mu-a" and "fsl,imx7s-mu-b" for i.MX7S or i.MX7D
+- reg : 	physical base address of the mailbox and length of
+		memory mapped region.
+- #mbox-cells:	Common mailbox binding property to identify the number
+		of cells required for the mailbox specifier. Should be 1.
+- interrupts :	interrupt number. The interrupt specifier format
+		depends on the interrupt controller parent.
+- clocks     :  phandle to the input clock.
+
+Example:
+	mu0a: mu@30aa0000 {
+		compatible = "fsl,imx7s-mu-a";
+		reg = <0x30aa0000 0x28>;
+		interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&clks IMX7D_MU_ROOT_CLK>;
+		#mbox-cells = <1>;
+	};
+
+	mu0b: mu@30ab0000 {
+		compatible = "fsl,imx7s-mu-b";
+		reg = <0x30ab0000 0x28>;
+		interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&clks IMX7D_MU_ROOT_CLK>;
+		#mbox-cells = <1>;
+	};
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH v1 2/4] dt-bindings: mailbox: provide imx-mailbox documentation
@ 2018-06-01  6:58   ` Oleksij Rempel
  0 siblings, 0 replies; 54+ messages in thread
From: Oleksij Rempel @ 2018-06-01  6:58 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
---
 .../bindings/mailbox/imx-mailbox.txt          | 35 +++++++++++++++++++
 1 file changed, 35 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mailbox/imx-mailbox.txt

diff --git a/Documentation/devicetree/bindings/mailbox/imx-mailbox.txt b/Documentation/devicetree/bindings/mailbox/imx-mailbox.txt
new file mode 100644
index 000000000000..a45604b33039
--- /dev/null
+++ b/Documentation/devicetree/bindings/mailbox/imx-mailbox.txt
@@ -0,0 +1,35 @@
+i.MX Messaging Unit
+===================
+
+The i.MX Messaging Unit (MU) contains two register sets: "A" and "B". In most cases
+they are accessible from all Processor Units. On one hand, at least for mailbox functionality,
+it makes no difference which application or processor is using which set of the MU. On
+other hand, the register sets for each of the MU parts are not identical.
+
+Required properties:
+- compatible :	Shell be one of:
+                    "fsl,imx7s-mu-a" and "fsl,imx7s-mu-b" for i.MX7S or i.MX7D
+- reg : 	physical base address of the mailbox and length of
+		memory mapped region.
+- #mbox-cells:	Common mailbox binding property to identify the number
+		of cells required for the mailbox specifier. Should be 1.
+- interrupts :	interrupt number. The interrupt specifier format
+		depends on the interrupt controller parent.
+- clocks     :  phandle to the input clock.
+
+Example:
+	mu0a: mu at 30aa0000 {
+		compatible = "fsl,imx7s-mu-a";
+		reg = <0x30aa0000 0x28>;
+		interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&clks IMX7D_MU_ROOT_CLK>;
+		#mbox-cells = <1>;
+	};
+
+	mu0b: mu at 30ab0000 {
+		compatible = "fsl,imx7s-mu-b";
+		reg = <0x30ab0000 0x28>;
+		interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&clks IMX7D_MU_ROOT_CLK>;
+		#mbox-cells = <1>;
+	};
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH v1 3/4] ARM: dts: imx7s: add i.MX7 messaging unit support
  2018-06-01  6:58 ` Oleksij Rempel
  (?)
@ 2018-06-01  6:58   ` Oleksij Rempel
  -1 siblings, 0 replies; 54+ messages in thread
From: Oleksij Rempel @ 2018-06-01  6:58 UTC (permalink / raw)
  To: Shawn Guo, Fabio Estevam, Rob Herring, Mark Rutland
  Cc: Oleksij Rempel, linux-clk, linux-arm-kernel, kernel, devicetree

Define the Messaging Unit (MU) for i.MX7 in the processor's dtsi.
The respective driver is added in the next commit.

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
---
 arch/arm/boot/dts/imx7s.dtsi | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/arch/arm/boot/dts/imx7s.dtsi b/arch/arm/boot/dts/imx7s.dtsi
index d9437e773b37..299bed72f69a 100644
--- a/arch/arm/boot/dts/imx7s.dtsi
+++ b/arch/arm/boot/dts/imx7s.dtsi
@@ -1008,6 +1008,24 @@
 				status = "disabled";
 			};
 
+			mu0a: mu@30aa0000 {
+				compatible = "fsl,imx7s-mu-a";
+				reg = <0x30aa0000 0x10000>;
+				interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX7D_MU_ROOT_CLK>;
+				#mbox-cells = <1>;
+				status = "disabled";
+			};
+
+			mu0b: mu@30ab0000 {
+				compatible = "fsl,imx7s-mu-b";
+				reg = <0x30ab0000 0x10000>;
+				interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX7D_MU_ROOT_CLK>;
+				#mbox-cells = <1>;
+				status = "disabled";
+			};
+
 			usbotg1: usb@30b10000 {
 				compatible = "fsl,imx7d-usb", "fsl,imx27-usb";
 				reg = <0x30b10000 0x200>;
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH v1 3/4] ARM: dts: imx7s: add i.MX7 messaging unit support
@ 2018-06-01  6:58   ` Oleksij Rempel
  0 siblings, 0 replies; 54+ messages in thread
From: Oleksij Rempel @ 2018-06-01  6:58 UTC (permalink / raw)
  To: Shawn Guo, Fabio Estevam, Rob Herring, Mark Rutland
  Cc: Oleksij Rempel, kernel, linux-arm-kernel, devicetree, linux-clk

Define the Messaging Unit (MU) for i.MX7 in the processor's dtsi.
The respective driver is added in the next commit.

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
---
 arch/arm/boot/dts/imx7s.dtsi | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/arch/arm/boot/dts/imx7s.dtsi b/arch/arm/boot/dts/imx7s.dtsi
index d9437e773b37..299bed72f69a 100644
--- a/arch/arm/boot/dts/imx7s.dtsi
+++ b/arch/arm/boot/dts/imx7s.dtsi
@@ -1008,6 +1008,24 @@
 				status = "disabled";
 			};
 
+			mu0a: mu@30aa0000 {
+				compatible = "fsl,imx7s-mu-a";
+				reg = <0x30aa0000 0x10000>;
+				interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX7D_MU_ROOT_CLK>;
+				#mbox-cells = <1>;
+				status = "disabled";
+			};
+
+			mu0b: mu@30ab0000 {
+				compatible = "fsl,imx7s-mu-b";
+				reg = <0x30ab0000 0x10000>;
+				interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX7D_MU_ROOT_CLK>;
+				#mbox-cells = <1>;
+				status = "disabled";
+			};
+
 			usbotg1: usb@30b10000 {
 				compatible = "fsl,imx7d-usb", "fsl,imx27-usb";
 				reg = <0x30b10000 0x200>;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH v1 3/4] ARM: dts: imx7s: add i.MX7 messaging unit support
@ 2018-06-01  6:58   ` Oleksij Rempel
  0 siblings, 0 replies; 54+ messages in thread
From: Oleksij Rempel @ 2018-06-01  6:58 UTC (permalink / raw)
  To: linux-arm-kernel

Define the Messaging Unit (MU) for i.MX7 in the processor's dtsi.
The respective driver is added in the next commit.

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
---
 arch/arm/boot/dts/imx7s.dtsi | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/arch/arm/boot/dts/imx7s.dtsi b/arch/arm/boot/dts/imx7s.dtsi
index d9437e773b37..299bed72f69a 100644
--- a/arch/arm/boot/dts/imx7s.dtsi
+++ b/arch/arm/boot/dts/imx7s.dtsi
@@ -1008,6 +1008,24 @@
 				status = "disabled";
 			};
 
+			mu0a: mu at 30aa0000 {
+				compatible = "fsl,imx7s-mu-a";
+				reg = <0x30aa0000 0x10000>;
+				interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX7D_MU_ROOT_CLK>;
+				#mbox-cells = <1>;
+				status = "disabled";
+			};
+
+			mu0b: mu at 30ab0000 {
+				compatible = "fsl,imx7s-mu-b";
+				reg = <0x30ab0000 0x10000>;
+				interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
+				clocks = <&clks IMX7D_MU_ROOT_CLK>;
+				#mbox-cells = <1>;
+				status = "disabled";
+			};
+
 			usbotg1: usb at 30b10000 {
 				compatible = "fsl,imx7d-usb", "fsl,imx27-usb";
 				reg = <0x30b10000 0x200>;
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH v1 4/4] mailbox: Add support for i.MX7D messaging unit
  2018-06-01  6:58 ` Oleksij Rempel
  (?)
@ 2018-06-01  6:58   ` Oleksij Rempel
  -1 siblings, 0 replies; 54+ messages in thread
From: Oleksij Rempel @ 2018-06-01  6:58 UTC (permalink / raw)
  To: Shawn Guo, Fabio Estevam, Rob Herring, Mark Rutland
  Cc: Oleksij Rempel, linux-clk, linux-arm-kernel, kernel, devicetree

The Mailbox controller is able to send messages (up to 4 32 bit words)
between the endpoints.

This driver was tested using the mailbox-test driver sending messages
between the Cortex-A7 and the Cortex-M4.

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
---
 drivers/mailbox/Kconfig       |   6 +
 drivers/mailbox/Makefile      |   2 +
 drivers/mailbox/imx-mailbox.c | 289 ++++++++++++++++++++++++++++++++++
 3 files changed, 297 insertions(+)
 create mode 100644 drivers/mailbox/imx-mailbox.c

diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
index a2bb27446dce..e1d2738a2e4c 100644
--- a/drivers/mailbox/Kconfig
+++ b/drivers/mailbox/Kconfig
@@ -15,6 +15,12 @@ config ARM_MHU
 	  The controller has 3 mailbox channels, the last of which can be
 	  used in Secure mode only.
 
+config IMX_MBOX
+	tristate "iMX Mailbox"
+	depends on SOC_IMX7D || COMPILE_TEST
+	help
+	  Mailbox implementation for iMX7D Messaging Unit (MU).
+
 config PLATFORM_MHU
 	tristate "Platform MHU Mailbox"
 	depends on OF
diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
index cc23c3a43fcd..ba2fe1b6dd62 100644
--- a/drivers/mailbox/Makefile
+++ b/drivers/mailbox/Makefile
@@ -7,6 +7,8 @@ obj-$(CONFIG_MAILBOX_TEST)	+= mailbox-test.o
 
 obj-$(CONFIG_ARM_MHU)	+= arm_mhu.o
 
+obj-$(CONFIG_IMX_MBOX)	+= imx-mailbox.o
+
 obj-$(CONFIG_PLATFORM_MHU)	+= platform_mhu.o
 
 obj-$(CONFIG_PL320_MBOX)	+= pl320-ipc.o
diff --git a/drivers/mailbox/imx-mailbox.c b/drivers/mailbox/imx-mailbox.c
new file mode 100644
index 000000000000..2bc9f11393b1
--- /dev/null
+++ b/drivers/mailbox/imx-mailbox.c
@@ -0,0 +1,289 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018 Pengutronix, Oleksij Rempel <o.rempel@pengutronix.de>
+ */
+
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/mailbox_controller.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+
+/* Transmit Register */
+#define IMX_MU_xTRn(x)		(0x00 + 4 * (x))
+/* Receive Register */
+#define IMX_MU_xRRn(x)		(0x10 + 4 * (x))
+/* Status Register */
+#define IMX_MU_xSR		0x20
+#define IMX_MU_xSR_TEn(x)	BIT(20 + (x))
+#define IMX_MU_xSR_RFn(x)	BIT(24 + (x))
+#define IMX_MU_xSR_BRDIP	BIT(9)
+
+/* Control Register */
+#define IMX_MU_xCR		0x24
+/* Transmit Interrupt Enable */
+#define IMX_MU_xCR_TIEn(x)	BIT(20 + (x))
+/* Receive Interrupt Enable */
+#define IMX_MU_xCR_RIEn(x)	BIT(24 + (x))
+
+#define IMX_MU_MAX_CHANS	4u
+
+struct imx_mu_priv;
+
+struct imx_mu_cfg {
+	unsigned int		chans;
+	void (*init_hw)(struct imx_mu_priv *priv);
+};
+
+struct imx_mu_con_priv {
+	int			irq;
+	unsigned int		bidx;
+	unsigned int		idx;
+};
+
+struct imx_mu_priv {
+	struct device		*dev;
+	const struct imx_mu_cfg	*dcfg;
+	void __iomem		*base;
+
+	struct mbox_controller	mbox;
+	struct mbox_chan	mbox_chans[IMX_MU_MAX_CHANS];
+
+	struct imx_mu_con_priv  con_priv[IMX_MU_MAX_CHANS];
+	struct clk		*clk;
+};
+
+static struct imx_mu_priv *to_imx_mu_priv(struct mbox_controller *mbox)
+{
+	return container_of(mbox, struct imx_mu_priv, mbox);
+}
+
+static void imx_mu_write(struct imx_mu_priv *priv, u32 val, u32 offs)
+{
+	iowrite32(val, priv->base + offs);
+}
+
+static u32 imx_mu_read(struct imx_mu_priv *priv, u32 offs)
+{
+	return ioread32(priv->base + offs);
+}
+
+static u32 imx_mu_rmw(struct imx_mu_priv *priv, u32 offs, u32 set, u32 clr)
+{
+	u32 val;
+
+	val = imx_mu_read(priv, offs);
+	val &= ~clr;
+	val |= set;
+	imx_mu_write(priv, val, offs);
+
+	return val;
+}
+
+static irqreturn_t imx_mu_isr(int irq, void *p)
+{
+	struct mbox_chan *chan = p;
+	struct imx_mu_con_priv *cp = chan->con_priv;
+	struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
+
+	u32 val, dat;
+
+	val = imx_mu_read(priv, IMX_MU_xSR);
+	val &= IMX_MU_xSR_TEn(cp->bidx) | IMX_MU_xSR_RFn(cp->bidx);
+	if (!val)
+		return IRQ_NONE;
+
+	if (val & IMX_MU_xSR_TEn(cp->bidx)) {
+		imx_mu_rmw(priv, IMX_MU_xCR, 0, IMX_MU_xCR_TIEn(cp->bidx));
+		mbox_chan_txdone(chan, 0);
+	}
+
+	if (val & IMX_MU_xSR_RFn(cp->bidx)) {
+		dat = imx_mu_read(priv, IMX_MU_xRRn(cp->idx));
+		mbox_chan_received_data(chan, (void *)&dat);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static bool imx_mu_last_tx_done(struct mbox_chan *chan)
+{
+	struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
+	struct imx_mu_con_priv *cp = chan->con_priv;
+	u32 val;
+
+	val = imx_mu_read(priv, IMX_MU_xSR);
+	/* test if transmit register is empty */
+	return (!(val & IMX_MU_xSR_TEn(cp->bidx)));
+}
+
+static int imx_mu_send_data(struct mbox_chan *chan, void *data)
+{
+	struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
+	struct imx_mu_con_priv *cp = chan->con_priv;
+	u32 *arg = data;
+
+	if (imx_mu_last_tx_done(chan))
+		return -EBUSY;
+
+	imx_mu_write(priv, *arg, IMX_MU_xTRn(cp->idx));
+	imx_mu_rmw(priv, IMX_MU_xCR, IMX_MU_xSR_TEn(cp->bidx), 0);
+
+	return 0;
+}
+
+static int imx_mu_startup(struct mbox_chan *chan)
+{
+	struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
+	struct imx_mu_con_priv *cp = chan->con_priv;
+	int ret;
+
+	ret = request_irq(cp->irq, imx_mu_isr,
+			  IRQF_SHARED, "imx_mu_chan", chan);
+	if (ret) {
+		dev_err(chan->mbox->dev,
+			"Unable to acquire IRQ %d\n", cp->irq);
+		return ret;
+	}
+
+	imx_mu_rmw(priv, IMX_MU_xCR, IMX_MU_xCR_RIEn(cp->bidx), 0);
+
+	return 0;
+}
+
+static void imx_mu_shutdown(struct mbox_chan *chan)
+{
+	struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
+	struct imx_mu_con_priv *cp = chan->con_priv;
+
+	imx_mu_rmw(priv, IMX_MU_xCR, 0,
+		   IMX_MU_xCR_TIEn(cp->bidx) | IMX_MU_xCR_RIEn(cp->bidx));
+
+	free_irq(cp->irq, chan);
+}
+
+static const struct mbox_chan_ops imx_mu_ops = {
+	.send_data = imx_mu_send_data,
+	.startup = imx_mu_startup,
+	.shutdown = imx_mu_shutdown,
+	.last_tx_done = imx_mu_last_tx_done,
+};
+
+static int imx_mu_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct resource *iomem;
+	struct imx_mu_priv *priv;
+	const struct imx_mu_cfg *dcfg;
+	unsigned int i, chans;
+	int irq, ret;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	dcfg = of_device_get_match_data(dev);
+	if (!dcfg)
+		return -EINVAL;
+
+	priv->dcfg = dcfg;
+	priv->dev = dev;
+
+	iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	priv->base = devm_ioremap_resource(&pdev->dev, iomem);
+	if (IS_ERR(priv->base))
+		return PTR_ERR(priv->base);
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq <= 0)
+		return irq < 0 ? irq : -EINVAL;
+
+	priv->clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(priv->clk)) {
+		if (PTR_ERR(priv->clk) == -ENOENT) {
+			priv->clk = NULL;
+		} else {
+			dev_err(dev, "Failed to get clock\n");
+			return PTR_ERR(priv->clk);
+		}
+	}
+
+	ret = clk_prepare_enable(priv->clk);
+	if (ret) {
+		dev_err(dev, "Failed to enable clock\n");
+		return ret;
+	}
+
+	chans = min(dcfg->chans, IMX_MU_MAX_CHANS);
+	/* Initialize channel identifiers */
+	for (i = 0; i < chans; i++) {
+		struct imx_mu_con_priv *cp = &priv->con_priv[i];
+
+		cp->bidx = 3 - i;
+		cp->idx = i;
+		cp->irq = irq;
+		priv->mbox_chans[i].con_priv = cp;
+	}
+
+	priv->mbox.dev = dev;
+	priv->mbox.ops = &imx_mu_ops;
+	priv->mbox.chans = priv->mbox_chans;
+	priv->mbox.num_chans = chans;
+	priv->mbox.txdone_irq = true;
+
+	platform_set_drvdata(pdev, priv);
+
+	if (priv->dcfg->init_hw)
+		priv->dcfg->init_hw(priv);
+
+	return mbox_controller_register(&priv->mbox);
+}
+
+static int imx_mu_remove(struct platform_device *pdev)
+{
+	struct imx_mu_priv *priv = platform_get_drvdata(pdev);
+
+	mbox_controller_unregister(&priv->mbox);
+	clk_disable_unprepare(priv->clk);
+
+	return 0;
+}
+
+
+static void imx_mu_init_imx7d_a(struct imx_mu_priv *priv)
+{
+	/* Set default config */
+	imx_mu_write(priv, 0, IMX_MU_xCR);
+}
+
+static const struct imx_mu_cfg imx_mu_cfg_imx7d_a = {
+	.chans = IMX_MU_MAX_CHANS,
+	.init_hw = imx_mu_init_imx7d_a,
+};
+
+static const struct imx_mu_cfg imx_mu_cfg_imx7d_b = {
+	.chans = IMX_MU_MAX_CHANS,
+};
+
+static const struct of_device_id imx_mu_dt_ids[] = {
+	{ .compatible = "fsl,imx7s-mu-a", .data = &imx_mu_cfg_imx7d_a },
+	{ .compatible = "fsl,imx7s-mu-b", .data = &imx_mu_cfg_imx7d_b },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, imx_mu_dt_ids);
+
+static struct platform_driver imx_mu_driver = {
+	.probe		= imx_mu_probe,
+	.remove		= imx_mu_remove,
+	.driver = {
+		.name	= "imx_mu",
+		.of_match_table = imx_mu_dt_ids,
+	},
+};
+module_platform_driver(imx_mu_driver);
+
+MODULE_AUTHOR("Oleksij Rempel <o.rempel@pengutronix.de>");
+MODULE_DESCRIPTION("Message Unit driver for i.MX7");
+MODULE_LICENSE("GPL v2");
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH v1 4/4] mailbox: Add support for i.MX7D messaging unit
@ 2018-06-01  6:58   ` Oleksij Rempel
  0 siblings, 0 replies; 54+ messages in thread
From: Oleksij Rempel @ 2018-06-01  6:58 UTC (permalink / raw)
  To: Shawn Guo, Fabio Estevam, Rob Herring, Mark Rutland
  Cc: Oleksij Rempel, kernel, linux-arm-kernel, devicetree, linux-clk

The Mailbox controller is able to send messages (up to 4 32 bit words)
between the endpoints.

This driver was tested using the mailbox-test driver sending messages
between the Cortex-A7 and the Cortex-M4.

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
---
 drivers/mailbox/Kconfig       |   6 +
 drivers/mailbox/Makefile      |   2 +
 drivers/mailbox/imx-mailbox.c | 289 ++++++++++++++++++++++++++++++++++
 3 files changed, 297 insertions(+)
 create mode 100644 drivers/mailbox/imx-mailbox.c

diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
index a2bb27446dce..e1d2738a2e4c 100644
--- a/drivers/mailbox/Kconfig
+++ b/drivers/mailbox/Kconfig
@@ -15,6 +15,12 @@ config ARM_MHU
 	  The controller has 3 mailbox channels, the last of which can be
 	  used in Secure mode only.
 
+config IMX_MBOX
+	tristate "iMX Mailbox"
+	depends on SOC_IMX7D || COMPILE_TEST
+	help
+	  Mailbox implementation for iMX7D Messaging Unit (MU).
+
 config PLATFORM_MHU
 	tristate "Platform MHU Mailbox"
 	depends on OF
diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
index cc23c3a43fcd..ba2fe1b6dd62 100644
--- a/drivers/mailbox/Makefile
+++ b/drivers/mailbox/Makefile
@@ -7,6 +7,8 @@ obj-$(CONFIG_MAILBOX_TEST)	+= mailbox-test.o
 
 obj-$(CONFIG_ARM_MHU)	+= arm_mhu.o
 
+obj-$(CONFIG_IMX_MBOX)	+= imx-mailbox.o
+
 obj-$(CONFIG_PLATFORM_MHU)	+= platform_mhu.o
 
 obj-$(CONFIG_PL320_MBOX)	+= pl320-ipc.o
diff --git a/drivers/mailbox/imx-mailbox.c b/drivers/mailbox/imx-mailbox.c
new file mode 100644
index 000000000000..2bc9f11393b1
--- /dev/null
+++ b/drivers/mailbox/imx-mailbox.c
@@ -0,0 +1,289 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018 Pengutronix, Oleksij Rempel <o.rempel@pengutronix.de>
+ */
+
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/mailbox_controller.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+
+/* Transmit Register */
+#define IMX_MU_xTRn(x)		(0x00 + 4 * (x))
+/* Receive Register */
+#define IMX_MU_xRRn(x)		(0x10 + 4 * (x))
+/* Status Register */
+#define IMX_MU_xSR		0x20
+#define IMX_MU_xSR_TEn(x)	BIT(20 + (x))
+#define IMX_MU_xSR_RFn(x)	BIT(24 + (x))
+#define IMX_MU_xSR_BRDIP	BIT(9)
+
+/* Control Register */
+#define IMX_MU_xCR		0x24
+/* Transmit Interrupt Enable */
+#define IMX_MU_xCR_TIEn(x)	BIT(20 + (x))
+/* Receive Interrupt Enable */
+#define IMX_MU_xCR_RIEn(x)	BIT(24 + (x))
+
+#define IMX_MU_MAX_CHANS	4u
+
+struct imx_mu_priv;
+
+struct imx_mu_cfg {
+	unsigned int		chans;
+	void (*init_hw)(struct imx_mu_priv *priv);
+};
+
+struct imx_mu_con_priv {
+	int			irq;
+	unsigned int		bidx;
+	unsigned int		idx;
+};
+
+struct imx_mu_priv {
+	struct device		*dev;
+	const struct imx_mu_cfg	*dcfg;
+	void __iomem		*base;
+
+	struct mbox_controller	mbox;
+	struct mbox_chan	mbox_chans[IMX_MU_MAX_CHANS];
+
+	struct imx_mu_con_priv  con_priv[IMX_MU_MAX_CHANS];
+	struct clk		*clk;
+};
+
+static struct imx_mu_priv *to_imx_mu_priv(struct mbox_controller *mbox)
+{
+	return container_of(mbox, struct imx_mu_priv, mbox);
+}
+
+static void imx_mu_write(struct imx_mu_priv *priv, u32 val, u32 offs)
+{
+	iowrite32(val, priv->base + offs);
+}
+
+static u32 imx_mu_read(struct imx_mu_priv *priv, u32 offs)
+{
+	return ioread32(priv->base + offs);
+}
+
+static u32 imx_mu_rmw(struct imx_mu_priv *priv, u32 offs, u32 set, u32 clr)
+{
+	u32 val;
+
+	val = imx_mu_read(priv, offs);
+	val &= ~clr;
+	val |= set;
+	imx_mu_write(priv, val, offs);
+
+	return val;
+}
+
+static irqreturn_t imx_mu_isr(int irq, void *p)
+{
+	struct mbox_chan *chan = p;
+	struct imx_mu_con_priv *cp = chan->con_priv;
+	struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
+
+	u32 val, dat;
+
+	val = imx_mu_read(priv, IMX_MU_xSR);
+	val &= IMX_MU_xSR_TEn(cp->bidx) | IMX_MU_xSR_RFn(cp->bidx);
+	if (!val)
+		return IRQ_NONE;
+
+	if (val & IMX_MU_xSR_TEn(cp->bidx)) {
+		imx_mu_rmw(priv, IMX_MU_xCR, 0, IMX_MU_xCR_TIEn(cp->bidx));
+		mbox_chan_txdone(chan, 0);
+	}
+
+	if (val & IMX_MU_xSR_RFn(cp->bidx)) {
+		dat = imx_mu_read(priv, IMX_MU_xRRn(cp->idx));
+		mbox_chan_received_data(chan, (void *)&dat);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static bool imx_mu_last_tx_done(struct mbox_chan *chan)
+{
+	struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
+	struct imx_mu_con_priv *cp = chan->con_priv;
+	u32 val;
+
+	val = imx_mu_read(priv, IMX_MU_xSR);
+	/* test if transmit register is empty */
+	return (!(val & IMX_MU_xSR_TEn(cp->bidx)));
+}
+
+static int imx_mu_send_data(struct mbox_chan *chan, void *data)
+{
+	struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
+	struct imx_mu_con_priv *cp = chan->con_priv;
+	u32 *arg = data;
+
+	if (imx_mu_last_tx_done(chan))
+		return -EBUSY;
+
+	imx_mu_write(priv, *arg, IMX_MU_xTRn(cp->idx));
+	imx_mu_rmw(priv, IMX_MU_xCR, IMX_MU_xSR_TEn(cp->bidx), 0);
+
+	return 0;
+}
+
+static int imx_mu_startup(struct mbox_chan *chan)
+{
+	struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
+	struct imx_mu_con_priv *cp = chan->con_priv;
+	int ret;
+
+	ret = request_irq(cp->irq, imx_mu_isr,
+			  IRQF_SHARED, "imx_mu_chan", chan);
+	if (ret) {
+		dev_err(chan->mbox->dev,
+			"Unable to acquire IRQ %d\n", cp->irq);
+		return ret;
+	}
+
+	imx_mu_rmw(priv, IMX_MU_xCR, IMX_MU_xCR_RIEn(cp->bidx), 0);
+
+	return 0;
+}
+
+static void imx_mu_shutdown(struct mbox_chan *chan)
+{
+	struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
+	struct imx_mu_con_priv *cp = chan->con_priv;
+
+	imx_mu_rmw(priv, IMX_MU_xCR, 0,
+		   IMX_MU_xCR_TIEn(cp->bidx) | IMX_MU_xCR_RIEn(cp->bidx));
+
+	free_irq(cp->irq, chan);
+}
+
+static const struct mbox_chan_ops imx_mu_ops = {
+	.send_data = imx_mu_send_data,
+	.startup = imx_mu_startup,
+	.shutdown = imx_mu_shutdown,
+	.last_tx_done = imx_mu_last_tx_done,
+};
+
+static int imx_mu_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct resource *iomem;
+	struct imx_mu_priv *priv;
+	const struct imx_mu_cfg *dcfg;
+	unsigned int i, chans;
+	int irq, ret;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	dcfg = of_device_get_match_data(dev);
+	if (!dcfg)
+		return -EINVAL;
+
+	priv->dcfg = dcfg;
+	priv->dev = dev;
+
+	iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	priv->base = devm_ioremap_resource(&pdev->dev, iomem);
+	if (IS_ERR(priv->base))
+		return PTR_ERR(priv->base);
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq <= 0)
+		return irq < 0 ? irq : -EINVAL;
+
+	priv->clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(priv->clk)) {
+		if (PTR_ERR(priv->clk) == -ENOENT) {
+			priv->clk = NULL;
+		} else {
+			dev_err(dev, "Failed to get clock\n");
+			return PTR_ERR(priv->clk);
+		}
+	}
+
+	ret = clk_prepare_enable(priv->clk);
+	if (ret) {
+		dev_err(dev, "Failed to enable clock\n");
+		return ret;
+	}
+
+	chans = min(dcfg->chans, IMX_MU_MAX_CHANS);
+	/* Initialize channel identifiers */
+	for (i = 0; i < chans; i++) {
+		struct imx_mu_con_priv *cp = &priv->con_priv[i];
+
+		cp->bidx = 3 - i;
+		cp->idx = i;
+		cp->irq = irq;
+		priv->mbox_chans[i].con_priv = cp;
+	}
+
+	priv->mbox.dev = dev;
+	priv->mbox.ops = &imx_mu_ops;
+	priv->mbox.chans = priv->mbox_chans;
+	priv->mbox.num_chans = chans;
+	priv->mbox.txdone_irq = true;
+
+	platform_set_drvdata(pdev, priv);
+
+	if (priv->dcfg->init_hw)
+		priv->dcfg->init_hw(priv);
+
+	return mbox_controller_register(&priv->mbox);
+}
+
+static int imx_mu_remove(struct platform_device *pdev)
+{
+	struct imx_mu_priv *priv = platform_get_drvdata(pdev);
+
+	mbox_controller_unregister(&priv->mbox);
+	clk_disable_unprepare(priv->clk);
+
+	return 0;
+}
+
+
+static void imx_mu_init_imx7d_a(struct imx_mu_priv *priv)
+{
+	/* Set default config */
+	imx_mu_write(priv, 0, IMX_MU_xCR);
+}
+
+static const struct imx_mu_cfg imx_mu_cfg_imx7d_a = {
+	.chans = IMX_MU_MAX_CHANS,
+	.init_hw = imx_mu_init_imx7d_a,
+};
+
+static const struct imx_mu_cfg imx_mu_cfg_imx7d_b = {
+	.chans = IMX_MU_MAX_CHANS,
+};
+
+static const struct of_device_id imx_mu_dt_ids[] = {
+	{ .compatible = "fsl,imx7s-mu-a", .data = &imx_mu_cfg_imx7d_a },
+	{ .compatible = "fsl,imx7s-mu-b", .data = &imx_mu_cfg_imx7d_b },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, imx_mu_dt_ids);
+
+static struct platform_driver imx_mu_driver = {
+	.probe		= imx_mu_probe,
+	.remove		= imx_mu_remove,
+	.driver = {
+		.name	= "imx_mu",
+		.of_match_table = imx_mu_dt_ids,
+	},
+};
+module_platform_driver(imx_mu_driver);
+
+MODULE_AUTHOR("Oleksij Rempel <o.rempel@pengutronix.de>");
+MODULE_DESCRIPTION("Message Unit driver for i.MX7");
+MODULE_LICENSE("GPL v2");
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 54+ messages in thread

* [PATCH v1 4/4] mailbox: Add support for i.MX7D messaging unit
@ 2018-06-01  6:58   ` Oleksij Rempel
  0 siblings, 0 replies; 54+ messages in thread
From: Oleksij Rempel @ 2018-06-01  6:58 UTC (permalink / raw)
  To: linux-arm-kernel

The Mailbox controller is able to send messages (up to 4 32 bit words)
between the endpoints.

This driver was tested using the mailbox-test driver sending messages
between the Cortex-A7 and the Cortex-M4.

Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
---
 drivers/mailbox/Kconfig       |   6 +
 drivers/mailbox/Makefile      |   2 +
 drivers/mailbox/imx-mailbox.c | 289 ++++++++++++++++++++++++++++++++++
 3 files changed, 297 insertions(+)
 create mode 100644 drivers/mailbox/imx-mailbox.c

diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
index a2bb27446dce..e1d2738a2e4c 100644
--- a/drivers/mailbox/Kconfig
+++ b/drivers/mailbox/Kconfig
@@ -15,6 +15,12 @@ config ARM_MHU
 	  The controller has 3 mailbox channels, the last of which can be
 	  used in Secure mode only.
 
+config IMX_MBOX
+	tristate "iMX Mailbox"
+	depends on SOC_IMX7D || COMPILE_TEST
+	help
+	  Mailbox implementation for iMX7D Messaging Unit (MU).
+
 config PLATFORM_MHU
 	tristate "Platform MHU Mailbox"
 	depends on OF
diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
index cc23c3a43fcd..ba2fe1b6dd62 100644
--- a/drivers/mailbox/Makefile
+++ b/drivers/mailbox/Makefile
@@ -7,6 +7,8 @@ obj-$(CONFIG_MAILBOX_TEST)	+= mailbox-test.o
 
 obj-$(CONFIG_ARM_MHU)	+= arm_mhu.o
 
+obj-$(CONFIG_IMX_MBOX)	+= imx-mailbox.o
+
 obj-$(CONFIG_PLATFORM_MHU)	+= platform_mhu.o
 
 obj-$(CONFIG_PL320_MBOX)	+= pl320-ipc.o
diff --git a/drivers/mailbox/imx-mailbox.c b/drivers/mailbox/imx-mailbox.c
new file mode 100644
index 000000000000..2bc9f11393b1
--- /dev/null
+++ b/drivers/mailbox/imx-mailbox.c
@@ -0,0 +1,289 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018 Pengutronix, Oleksij Rempel <o.rempel@pengutronix.de>
+ */
+
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/mailbox_controller.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+
+/* Transmit Register */
+#define IMX_MU_xTRn(x)		(0x00 + 4 * (x))
+/* Receive Register */
+#define IMX_MU_xRRn(x)		(0x10 + 4 * (x))
+/* Status Register */
+#define IMX_MU_xSR		0x20
+#define IMX_MU_xSR_TEn(x)	BIT(20 + (x))
+#define IMX_MU_xSR_RFn(x)	BIT(24 + (x))
+#define IMX_MU_xSR_BRDIP	BIT(9)
+
+/* Control Register */
+#define IMX_MU_xCR		0x24
+/* Transmit Interrupt Enable */
+#define IMX_MU_xCR_TIEn(x)	BIT(20 + (x))
+/* Receive Interrupt Enable */
+#define IMX_MU_xCR_RIEn(x)	BIT(24 + (x))
+
+#define IMX_MU_MAX_CHANS	4u
+
+struct imx_mu_priv;
+
+struct imx_mu_cfg {
+	unsigned int		chans;
+	void (*init_hw)(struct imx_mu_priv *priv);
+};
+
+struct imx_mu_con_priv {
+	int			irq;
+	unsigned int		bidx;
+	unsigned int		idx;
+};
+
+struct imx_mu_priv {
+	struct device		*dev;
+	const struct imx_mu_cfg	*dcfg;
+	void __iomem		*base;
+
+	struct mbox_controller	mbox;
+	struct mbox_chan	mbox_chans[IMX_MU_MAX_CHANS];
+
+	struct imx_mu_con_priv  con_priv[IMX_MU_MAX_CHANS];
+	struct clk		*clk;
+};
+
+static struct imx_mu_priv *to_imx_mu_priv(struct mbox_controller *mbox)
+{
+	return container_of(mbox, struct imx_mu_priv, mbox);
+}
+
+static void imx_mu_write(struct imx_mu_priv *priv, u32 val, u32 offs)
+{
+	iowrite32(val, priv->base + offs);
+}
+
+static u32 imx_mu_read(struct imx_mu_priv *priv, u32 offs)
+{
+	return ioread32(priv->base + offs);
+}
+
+static u32 imx_mu_rmw(struct imx_mu_priv *priv, u32 offs, u32 set, u32 clr)
+{
+	u32 val;
+
+	val = imx_mu_read(priv, offs);
+	val &= ~clr;
+	val |= set;
+	imx_mu_write(priv, val, offs);
+
+	return val;
+}
+
+static irqreturn_t imx_mu_isr(int irq, void *p)
+{
+	struct mbox_chan *chan = p;
+	struct imx_mu_con_priv *cp = chan->con_priv;
+	struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
+
+	u32 val, dat;
+
+	val = imx_mu_read(priv, IMX_MU_xSR);
+	val &= IMX_MU_xSR_TEn(cp->bidx) | IMX_MU_xSR_RFn(cp->bidx);
+	if (!val)
+		return IRQ_NONE;
+
+	if (val & IMX_MU_xSR_TEn(cp->bidx)) {
+		imx_mu_rmw(priv, IMX_MU_xCR, 0, IMX_MU_xCR_TIEn(cp->bidx));
+		mbox_chan_txdone(chan, 0);
+	}
+
+	if (val & IMX_MU_xSR_RFn(cp->bidx)) {
+		dat = imx_mu_read(priv, IMX_MU_xRRn(cp->idx));
+		mbox_chan_received_data(chan, (void *)&dat);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static bool imx_mu_last_tx_done(struct mbox_chan *chan)
+{
+	struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
+	struct imx_mu_con_priv *cp = chan->con_priv;
+	u32 val;
+
+	val = imx_mu_read(priv, IMX_MU_xSR);
+	/* test if transmit register is empty */
+	return (!(val & IMX_MU_xSR_TEn(cp->bidx)));
+}
+
+static int imx_mu_send_data(struct mbox_chan *chan, void *data)
+{
+	struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
+	struct imx_mu_con_priv *cp = chan->con_priv;
+	u32 *arg = data;
+
+	if (imx_mu_last_tx_done(chan))
+		return -EBUSY;
+
+	imx_mu_write(priv, *arg, IMX_MU_xTRn(cp->idx));
+	imx_mu_rmw(priv, IMX_MU_xCR, IMX_MU_xSR_TEn(cp->bidx), 0);
+
+	return 0;
+}
+
+static int imx_mu_startup(struct mbox_chan *chan)
+{
+	struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
+	struct imx_mu_con_priv *cp = chan->con_priv;
+	int ret;
+
+	ret = request_irq(cp->irq, imx_mu_isr,
+			  IRQF_SHARED, "imx_mu_chan", chan);
+	if (ret) {
+		dev_err(chan->mbox->dev,
+			"Unable to acquire IRQ %d\n", cp->irq);
+		return ret;
+	}
+
+	imx_mu_rmw(priv, IMX_MU_xCR, IMX_MU_xCR_RIEn(cp->bidx), 0);
+
+	return 0;
+}
+
+static void imx_mu_shutdown(struct mbox_chan *chan)
+{
+	struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
+	struct imx_mu_con_priv *cp = chan->con_priv;
+
+	imx_mu_rmw(priv, IMX_MU_xCR, 0,
+		   IMX_MU_xCR_TIEn(cp->bidx) | IMX_MU_xCR_RIEn(cp->bidx));
+
+	free_irq(cp->irq, chan);
+}
+
+static const struct mbox_chan_ops imx_mu_ops = {
+	.send_data = imx_mu_send_data,
+	.startup = imx_mu_startup,
+	.shutdown = imx_mu_shutdown,
+	.last_tx_done = imx_mu_last_tx_done,
+};
+
+static int imx_mu_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct resource *iomem;
+	struct imx_mu_priv *priv;
+	const struct imx_mu_cfg *dcfg;
+	unsigned int i, chans;
+	int irq, ret;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	dcfg = of_device_get_match_data(dev);
+	if (!dcfg)
+		return -EINVAL;
+
+	priv->dcfg = dcfg;
+	priv->dev = dev;
+
+	iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	priv->base = devm_ioremap_resource(&pdev->dev, iomem);
+	if (IS_ERR(priv->base))
+		return PTR_ERR(priv->base);
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq <= 0)
+		return irq < 0 ? irq : -EINVAL;
+
+	priv->clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(priv->clk)) {
+		if (PTR_ERR(priv->clk) == -ENOENT) {
+			priv->clk = NULL;
+		} else {
+			dev_err(dev, "Failed to get clock\n");
+			return PTR_ERR(priv->clk);
+		}
+	}
+
+	ret = clk_prepare_enable(priv->clk);
+	if (ret) {
+		dev_err(dev, "Failed to enable clock\n");
+		return ret;
+	}
+
+	chans = min(dcfg->chans, IMX_MU_MAX_CHANS);
+	/* Initialize channel identifiers */
+	for (i = 0; i < chans; i++) {
+		struct imx_mu_con_priv *cp = &priv->con_priv[i];
+
+		cp->bidx = 3 - i;
+		cp->idx = i;
+		cp->irq = irq;
+		priv->mbox_chans[i].con_priv = cp;
+	}
+
+	priv->mbox.dev = dev;
+	priv->mbox.ops = &imx_mu_ops;
+	priv->mbox.chans = priv->mbox_chans;
+	priv->mbox.num_chans = chans;
+	priv->mbox.txdone_irq = true;
+
+	platform_set_drvdata(pdev, priv);
+
+	if (priv->dcfg->init_hw)
+		priv->dcfg->init_hw(priv);
+
+	return mbox_controller_register(&priv->mbox);
+}
+
+static int imx_mu_remove(struct platform_device *pdev)
+{
+	struct imx_mu_priv *priv = platform_get_drvdata(pdev);
+
+	mbox_controller_unregister(&priv->mbox);
+	clk_disable_unprepare(priv->clk);
+
+	return 0;
+}
+
+
+static void imx_mu_init_imx7d_a(struct imx_mu_priv *priv)
+{
+	/* Set default config */
+	imx_mu_write(priv, 0, IMX_MU_xCR);
+}
+
+static const struct imx_mu_cfg imx_mu_cfg_imx7d_a = {
+	.chans = IMX_MU_MAX_CHANS,
+	.init_hw = imx_mu_init_imx7d_a,
+};
+
+static const struct imx_mu_cfg imx_mu_cfg_imx7d_b = {
+	.chans = IMX_MU_MAX_CHANS,
+};
+
+static const struct of_device_id imx_mu_dt_ids[] = {
+	{ .compatible = "fsl,imx7s-mu-a", .data = &imx_mu_cfg_imx7d_a },
+	{ .compatible = "fsl,imx7s-mu-b", .data = &imx_mu_cfg_imx7d_b },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, imx_mu_dt_ids);
+
+static struct platform_driver imx_mu_driver = {
+	.probe		= imx_mu_probe,
+	.remove		= imx_mu_remove,
+	.driver = {
+		.name	= "imx_mu",
+		.of_match_table = imx_mu_dt_ids,
+	},
+};
+module_platform_driver(imx_mu_driver);
+
+MODULE_AUTHOR("Oleksij Rempel <o.rempel@pengutronix.de>");
+MODULE_DESCRIPTION("Message Unit driver for i.MX7");
+MODULE_LICENSE("GPL v2");
-- 
2.17.1

^ permalink raw reply related	[flat|nested] 54+ messages in thread

* Re: [PATCH v1 0/4] add mailbox support for i.MX7D
  2018-06-01  6:58 ` Oleksij Rempel
  (?)
@ 2018-06-01  8:34   ` Robert Schwebel
  -1 siblings, 0 replies; 54+ messages in thread
From: Robert Schwebel @ 2018-06-01  8:34 UTC (permalink / raw)
  To: Oleksij Rempel
  Cc: Mark Rutland, devicetree, Rob Herring, NXP Linux Team, kernel,
	A.s. Dong, Fabio Estevam, Shawn Guo, linux-clk, linux-arm-kernel

On Fri, Jun 01, 2018 at 08:58:17AM +0200, Oleksij Rempel wrote:
> This patches are providing support for mailbox (Messaging Unit) for
> i.MX7D. Functionality was tested on PHYTEC phyBOARD-Zeta i.MX7D with
> Linux running on all cores: ARM Cortex-A7 and ARM Cortex-M4.
> 
> Both parts of i.MX messaging Unit are visible for all CPUs available
> on i.MX7D. Communication worked independent of MU side in combination
> with CPU. For example MU-A used on ARM Cortex-A7 and MU-B used on ARM
> Cortex-M4 or other ways around.
> 
> The question to NXP developers: are there are limitations or
> recommendations about MU vs CPU combination? The i.MX7D documentation
> talks about "Processor A" and "Processor B". It is not quite clear
> what processor it actually is (A7 or M4).

Adding Dong Aisheng and NXP linux team to Cc:.

rsc
-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v1 0/4] add mailbox support for i.MX7D
@ 2018-06-01  8:34   ` Robert Schwebel
  0 siblings, 0 replies; 54+ messages in thread
From: Robert Schwebel @ 2018-06-01  8:34 UTC (permalink / raw)
  To: Oleksij Rempel
  Cc: Shawn Guo, Fabio Estevam, Rob Herring, Mark Rutland, linux-clk,
	linux-arm-kernel, kernel, devicetree, A.s. Dong, NXP Linux Team

On Fri, Jun 01, 2018 at 08:58:17AM +0200, Oleksij Rempel wrote:
> This patches are providing support for mailbox (Messaging Unit) for
> i.MX7D. Functionality was tested on PHYTEC phyBOARD-Zeta i.MX7D with
> Linux running on all cores: ARM Cortex-A7 and ARM Cortex-M4.
> 
> Both parts of i.MX messaging Unit are visible for all CPUs available
> on i.MX7D. Communication worked independent of MU side in combination
> with CPU. For example MU-A used on ARM Cortex-A7 and MU-B used on ARM
> Cortex-M4 or other ways around.
> 
> The question to NXP developers: are there are limitations or
> recommendations about MU vs CPU combination? The i.MX7D documentation
> talks about "Processor A" and "Processor B". It is not quite clear
> what processor it actually is (A7 or M4).

Adding Dong Aisheng and NXP linux team to Cc:.

rsc
-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 54+ messages in thread

* [PATCH v1 0/4] add mailbox support for i.MX7D
@ 2018-06-01  8:34   ` Robert Schwebel
  0 siblings, 0 replies; 54+ messages in thread
From: Robert Schwebel @ 2018-06-01  8:34 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Jun 01, 2018 at 08:58:17AM +0200, Oleksij Rempel wrote:
> This patches are providing support for mailbox (Messaging Unit) for
> i.MX7D. Functionality was tested on PHYTEC phyBOARD-Zeta i.MX7D with
> Linux running on all cores: ARM Cortex-A7 and ARM Cortex-M4.
> 
> Both parts of i.MX messaging Unit are visible for all CPUs available
> on i.MX7D. Communication worked independent of MU side in combination
> with CPU. For example MU-A used on ARM Cortex-A7 and MU-B used on ARM
> Cortex-M4 or other ways around.
> 
> The question to NXP developers: are there are limitations or
> recommendations about MU vs CPU combination? The i.MX7D documentation
> talks about "Processor A" and "Processor B". It is not quite clear
> what processor it actually is (A7 or M4).

Adding Dong Aisheng and NXP linux team to Cc:.

rsc
-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v1 2/4] dt-bindings: mailbox: provide imx-mailbox documentation
  2018-06-01  6:58   ` Oleksij Rempel
  (?)
@ 2018-06-12 19:41     ` Rob Herring
  -1 siblings, 0 replies; 54+ messages in thread
From: Rob Herring @ 2018-06-12 19:41 UTC (permalink / raw)
  To: Oleksij Rempel
  Cc: Mark Rutland, devicetree, kernel, Fabio Estevam, Shawn Guo,
	linux-clk, linux-arm-kernel

On Fri, Jun 01, 2018 at 08:58:19AM +0200, Oleksij Rempel wrote:
> Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
> ---
>  .../bindings/mailbox/imx-mailbox.txt          | 35 +++++++++++++++++++
>  1 file changed, 35 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mailbox/imx-mailbox.txt
> 
> diff --git a/Documentation/devicetree/bindings/mailbox/imx-mailbox.txt b/Documentation/devicetree/bindings/mailbox/imx-mailbox.txt
> new file mode 100644
> index 000000000000..a45604b33039
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mailbox/imx-mailbox.txt
> @@ -0,0 +1,35 @@
> +i.MX Messaging Unit
> +===================
> +
> +The i.MX Messaging Unit (MU) contains two register sets: "A" and "B". In most cases
> +they are accessible from all Processor Units. On one hand, at least for mailbox functionality,
> +it makes no difference which application or processor is using which set of the MU. On

Please wrap lines correctly (<80).

> +other hand, the register sets for each of the MU parts are not identical.
> +
> +Required properties:
> +- compatible :	Shell be one of:
> +                    "fsl,imx7s-mu-a" and "fsl,imx7s-mu-b" for i.MX7S or i.MX7D
> +- reg : 	physical base address of the mailbox and length of

Mix of space and tab.

> +		memory mapped region.
> +- #mbox-cells:	Common mailbox binding property to identify the number
> +		of cells required for the mailbox specifier. Should be 1.
> +- interrupts :	interrupt number. The interrupt specifier format
> +		depends on the interrupt controller parent.

Just need to say how many interrupts and what they are if more than 1.

> +- clocks     :  phandle to the input clock.
> +
> +Example:
> +	mu0a: mu@30aa0000 {

mailbox@...

> +		compatible = "fsl,imx7s-mu-a";
> +		reg = <0x30aa0000 0x28>;
> +		interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
> +		clocks = <&clks IMX7D_MU_ROOT_CLK>;
> +		#mbox-cells = <1>;
> +	};
> +
> +	mu0b: mu@30ab0000 {

mailbox@...

> +		compatible = "fsl,imx7s-mu-b";
> +		reg = <0x30ab0000 0x28>;
> +		interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
> +		clocks = <&clks IMX7D_MU_ROOT_CLK>;
> +		#mbox-cells = <1>;
> +	};
> -- 
> 2.17.1
> 

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v1 2/4] dt-bindings: mailbox: provide imx-mailbox documentation
@ 2018-06-12 19:41     ` Rob Herring
  0 siblings, 0 replies; 54+ messages in thread
From: Rob Herring @ 2018-06-12 19:41 UTC (permalink / raw)
  To: Oleksij Rempel
  Cc: Shawn Guo, Fabio Estevam, Mark Rutland, kernel, linux-arm-kernel,
	devicetree, linux-clk

On Fri, Jun 01, 2018 at 08:58:19AM +0200, Oleksij Rempel wrote:
> Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
> ---
>  .../bindings/mailbox/imx-mailbox.txt          | 35 +++++++++++++++++++
>  1 file changed, 35 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mailbox/imx-mailbox.txt
> 
> diff --git a/Documentation/devicetree/bindings/mailbox/imx-mailbox.txt b/Documentation/devicetree/bindings/mailbox/imx-mailbox.txt
> new file mode 100644
> index 000000000000..a45604b33039
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mailbox/imx-mailbox.txt
> @@ -0,0 +1,35 @@
> +i.MX Messaging Unit
> +===================
> +
> +The i.MX Messaging Unit (MU) contains two register sets: "A" and "B". In most cases
> +they are accessible from all Processor Units. On one hand, at least for mailbox functionality,
> +it makes no difference which application or processor is using which set of the MU. On

Please wrap lines correctly (<80).

> +other hand, the register sets for each of the MU parts are not identical.
> +
> +Required properties:
> +- compatible :	Shell be one of:
> +                    "fsl,imx7s-mu-a" and "fsl,imx7s-mu-b" for i.MX7S or i.MX7D
> +- reg : 	physical base address of the mailbox and length of

Mix of space and tab.

> +		memory mapped region.
> +- #mbox-cells:	Common mailbox binding property to identify the number
> +		of cells required for the mailbox specifier. Should be 1.
> +- interrupts :	interrupt number. The interrupt specifier format
> +		depends on the interrupt controller parent.

Just need to say how many interrupts and what they are if more than 1.

> +- clocks     :  phandle to the input clock.
> +
> +Example:
> +	mu0a: mu@30aa0000 {

mailbox@...

> +		compatible = "fsl,imx7s-mu-a";
> +		reg = <0x30aa0000 0x28>;
> +		interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
> +		clocks = <&clks IMX7D_MU_ROOT_CLK>;
> +		#mbox-cells = <1>;
> +	};
> +
> +	mu0b: mu@30ab0000 {

mailbox@...

> +		compatible = "fsl,imx7s-mu-b";
> +		reg = <0x30ab0000 0x28>;
> +		interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
> +		clocks = <&clks IMX7D_MU_ROOT_CLK>;
> +		#mbox-cells = <1>;
> +	};
> -- 
> 2.17.1
> 

^ permalink raw reply	[flat|nested] 54+ messages in thread

* [PATCH v1 2/4] dt-bindings: mailbox: provide imx-mailbox documentation
@ 2018-06-12 19:41     ` Rob Herring
  0 siblings, 0 replies; 54+ messages in thread
From: Rob Herring @ 2018-06-12 19:41 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Jun 01, 2018 at 08:58:19AM +0200, Oleksij Rempel wrote:
> Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
> ---
>  .../bindings/mailbox/imx-mailbox.txt          | 35 +++++++++++++++++++
>  1 file changed, 35 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mailbox/imx-mailbox.txt
> 
> diff --git a/Documentation/devicetree/bindings/mailbox/imx-mailbox.txt b/Documentation/devicetree/bindings/mailbox/imx-mailbox.txt
> new file mode 100644
> index 000000000000..a45604b33039
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mailbox/imx-mailbox.txt
> @@ -0,0 +1,35 @@
> +i.MX Messaging Unit
> +===================
> +
> +The i.MX Messaging Unit (MU) contains two register sets: "A" and "B". In most cases
> +they are accessible from all Processor Units. On one hand, at least for mailbox functionality,
> +it makes no difference which application or processor is using which set of the MU. On

Please wrap lines correctly (<80).

> +other hand, the register sets for each of the MU parts are not identical.
> +
> +Required properties:
> +- compatible :	Shell be one of:
> +                    "fsl,imx7s-mu-a" and "fsl,imx7s-mu-b" for i.MX7S or i.MX7D
> +- reg : 	physical base address of the mailbox and length of

Mix of space and tab.

> +		memory mapped region.
> +- #mbox-cells:	Common mailbox binding property to identify the number
> +		of cells required for the mailbox specifier. Should be 1.
> +- interrupts :	interrupt number. The interrupt specifier format
> +		depends on the interrupt controller parent.

Just need to say how many interrupts and what they are if more than 1.

> +- clocks     :  phandle to the input clock.
> +
> +Example:
> +	mu0a: mu at 30aa0000 {

mailbox at ...

> +		compatible = "fsl,imx7s-mu-a";
> +		reg = <0x30aa0000 0x28>;
> +		interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
> +		clocks = <&clks IMX7D_MU_ROOT_CLK>;
> +		#mbox-cells = <1>;
> +	};
> +
> +	mu0b: mu at 30ab0000 {

mailbox at ...

> +		compatible = "fsl,imx7s-mu-b";
> +		reg = <0x30ab0000 0x28>;
> +		interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
> +		clocks = <&clks IMX7D_MU_ROOT_CLK>;
> +		#mbox-cells = <1>;
> +	};
> -- 
> 2.17.1
> 

^ permalink raw reply	[flat|nested] 54+ messages in thread

* RE: [PATCH v1 0/4] add mailbox support for i.MX7D
  2018-06-01  8:34   ` Robert Schwebel
  (?)
@ 2018-06-13  9:36     ` A.s. Dong
  -1 siblings, 0 replies; 54+ messages in thread
From: A.s. Dong @ 2018-06-13  9:36 UTC (permalink / raw)
  To: Robert Schwebel, Oleksij Rempel
  Cc: Mark Rutland, devicetree, Rob Herring, dl-linux-imx, kernel,
	Fabio Estevam, Shawn Guo, linux-clk, linux-arm-kernel

Hi Robert,

Thanks for the forwarding.

> -----Original Message-----
> From: Robert Schwebel [mailto:r.schwebel@pengutronix.de]
> Sent: Friday, June 1, 2018 4:34 PM
> To: Oleksij Rempel <o.rempel@pengutronix.de>
> Cc: Shawn Guo <shawnguo@kernel.org>; Fabio Estevam
> <fabio.estevam@nxp.com>; Rob Herring <robh+dt@kernel.org>; Mark
> Rutland <mark.rutland@arm.com>; linux-clk@vger.kernel.org; linux-arm-
> kernel@lists.infradead.org; kernel@pengutronix.de;
> devicetree@vger.kernel.org; A.s. Dong <aisheng.dong@nxp.com>; dl-linux-
> imx <linux-imx@nxp.com>
> Subject: Re: [PATCH v1 0/4] add mailbox support for i.MX7D
> 
> On Fri, Jun 01, 2018 at 08:58:17AM +0200, Oleksij Rempel wrote:
> > This patches are providing support for mailbox (Messaging Unit) for
> > i.MX7D. Functionality was tested on PHYTEC phyBOARD-Zeta i.MX7D with
> > Linux running on all cores: ARM Cortex-A7 and ARM Cortex-M4.
> >

Thanks for the patch.

> > Both parts of i.MX messaging Unit are visible for all CPUs available
> > on i.MX7D. Communication worked independent of MU side in
> combination
> > with CPU. For example MU-A used on ARM Cortex-A7 and MU-B used on
> ARM
> > Cortex-M4 or other ways around.
> >
> > The question to NXP developers: are there are limitations or
> > recommendations about MU vs CPU combination? The i.MX7D
> documentation
> > talks about "Processor A" and "Processor B". It is not quite clear
> > what processor it actually is (A7 or M4).

The MU vs CPU combination usually are defined by HW design.
It, MU Side A/B,  can either be used by both CPU (A core and M core)
or fixed to one side.
For MX7D case, both side memory map can be accessed by both CPU
Including Interrupt signals. But the recommendation is A core using
MU side A and M core using MU side B.

Regards
Dong Aisheng

> 
> Adding Dong Aisheng and NXP linux team to Cc:.
> 
> rsc
> --
> Pengutronix e.K.                           |                             |
> Industrial Linux Solutions                 |
> https://emea01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fww
> w.pengutronix.de%2F&data=02%7C01%7Caisheng.dong%40nxp.com%7Cf53
> d9c9cdd744878740f08d5c79a7a1e%7C686ea1d3bc2b4c6fa92cd99c5c301635%7
> C0%7C0%7C636634388645464924&sdata=2ehh92tNbfwf3fJTp%2Fx7IUOgGSU
> h6pyrc2XsdRJkTw4%3D&reserved=0  |
> Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 54+ messages in thread

* RE: [PATCH v1 0/4] add mailbox support for i.MX7D
@ 2018-06-13  9:36     ` A.s. Dong
  0 siblings, 0 replies; 54+ messages in thread
From: A.s. Dong @ 2018-06-13  9:36 UTC (permalink / raw)
  To: Robert Schwebel, Oleksij Rempel
  Cc: Shawn Guo, Fabio Estevam, Rob Herring, Mark Rutland, linux-clk,
	linux-arm-kernel, kernel, devicetree, dl-linux-imx

Hi Robert,

Thanks for the forwarding.

> -----Original Message-----
> From: Robert Schwebel [mailto:r.schwebel@pengutronix.de]
> Sent: Friday, June 1, 2018 4:34 PM
> To: Oleksij Rempel <o.rempel@pengutronix.de>
> Cc: Shawn Guo <shawnguo@kernel.org>; Fabio Estevam
> <fabio.estevam@nxp.com>; Rob Herring <robh+dt@kernel.org>; Mark
> Rutland <mark.rutland@arm.com>; linux-clk@vger.kernel.org; linux-arm-
> kernel@lists.infradead.org; kernel@pengutronix.de;
> devicetree@vger.kernel.org; A.s. Dong <aisheng.dong@nxp.com>; dl-linux-
> imx <linux-imx@nxp.com>
> Subject: Re: [PATCH v1 0/4] add mailbox support for i.MX7D
>=20
> On Fri, Jun 01, 2018 at 08:58:17AM +0200, Oleksij Rempel wrote:
> > This patches are providing support for mailbox (Messaging Unit) for
> > i.MX7D. Functionality was tested on PHYTEC phyBOARD-Zeta i.MX7D with
> > Linux running on all cores: ARM Cortex-A7 and ARM Cortex-M4.
> >

Thanks for the patch.

> > Both parts of i.MX messaging Unit are visible for all CPUs available
> > on i.MX7D. Communication worked independent of MU side in
> combination
> > with CPU. For example MU-A used on ARM Cortex-A7 and MU-B used on
> ARM
> > Cortex-M4 or other ways around.
> >
> > The question to NXP developers: are there are limitations or
> > recommendations about MU vs CPU combination? The i.MX7D
> documentation
> > talks about "Processor A" and "Processor B". It is not quite clear
> > what processor it actually is (A7 or M4).

The MU vs CPU combination usually are defined by HW design.
It, MU Side A/B,  can either be used by both CPU (A core and M core)
or fixed to one side.
For MX7D case, both side memory map can be accessed by both CPU
Including Interrupt signals. But the recommendation is A core using
MU side A and M core using MU side B.

Regards
Dong Aisheng

>=20
> Adding Dong Aisheng and NXP linux team to Cc:.
>=20
> rsc
> --
> Pengutronix e.K.                           |                             =
|
> Industrial Linux Solutions                 |
> https://emea01.safelinks.protection.outlook.com/?url=3Dhttp%3A%2F%2Fww
> w.pengutronix.de%2F&data=3D02%7C01%7Caisheng.dong%40nxp.com%7Cf53
> d9c9cdd744878740f08d5c79a7a1e%7C686ea1d3bc2b4c6fa92cd99c5c301635%7
> C0%7C0%7C636634388645464924&sdata=3D2ehh92tNbfwf3fJTp%2Fx7IUOgGSU
> h6pyrc2XsdRJkTw4%3D&reserved=3D0  |
> Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    =
|
> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 =
|

^ permalink raw reply	[flat|nested] 54+ messages in thread

* [PATCH v1 0/4] add mailbox support for i.MX7D
@ 2018-06-13  9:36     ` A.s. Dong
  0 siblings, 0 replies; 54+ messages in thread
From: A.s. Dong @ 2018-06-13  9:36 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Robert,

Thanks for the forwarding.

> -----Original Message-----
> From: Robert Schwebel [mailto:r.schwebel at pengutronix.de]
> Sent: Friday, June 1, 2018 4:34 PM
> To: Oleksij Rempel <o.rempel@pengutronix.de>
> Cc: Shawn Guo <shawnguo@kernel.org>; Fabio Estevam
> <fabio.estevam@nxp.com>; Rob Herring <robh+dt@kernel.org>; Mark
> Rutland <mark.rutland@arm.com>; linux-clk at vger.kernel.org; linux-arm-
> kernel at lists.infradead.org; kernel at pengutronix.de;
> devicetree at vger.kernel.org; A.s. Dong <aisheng.dong@nxp.com>; dl-linux-
> imx <linux-imx@nxp.com>
> Subject: Re: [PATCH v1 0/4] add mailbox support for i.MX7D
> 
> On Fri, Jun 01, 2018 at 08:58:17AM +0200, Oleksij Rempel wrote:
> > This patches are providing support for mailbox (Messaging Unit) for
> > i.MX7D. Functionality was tested on PHYTEC phyBOARD-Zeta i.MX7D with
> > Linux running on all cores: ARM Cortex-A7 and ARM Cortex-M4.
> >

Thanks for the patch.

> > Both parts of i.MX messaging Unit are visible for all CPUs available
> > on i.MX7D. Communication worked independent of MU side in
> combination
> > with CPU. For example MU-A used on ARM Cortex-A7 and MU-B used on
> ARM
> > Cortex-M4 or other ways around.
> >
> > The question to NXP developers: are there are limitations or
> > recommendations about MU vs CPU combination? The i.MX7D
> documentation
> > talks about "Processor A" and "Processor B". It is not quite clear
> > what processor it actually is (A7 or M4).

The MU vs CPU combination usually are defined by HW design.
It, MU Side A/B,  can either be used by both CPU (A core and M core)
or fixed to one side.
For MX7D case, both side memory map can be accessed by both CPU
Including Interrupt signals. But the recommendation is A core using
MU side A and M core using MU side B.

Regards
Dong Aisheng

> 
> Adding Dong Aisheng and NXP linux team to Cc:.
> 
> rsc
> --
> Pengutronix e.K.                           |                             |
> Industrial Linux Solutions                 |
> https://emea01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fww
> w.pengutronix.de%2F&data=02%7C01%7Caisheng.dong%40nxp.com%7Cf53
> d9c9cdd744878740f08d5c79a7a1e%7C686ea1d3bc2b4c6fa92cd99c5c301635%7
> C0%7C0%7C636634388645464924&sdata=2ehh92tNbfwf3fJTp%2Fx7IUOgGSU
> h6pyrc2XsdRJkTw4%3D&reserved=0  |
> Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v1 1/4] clk: imx7d: add IMX7D_MU_ROOT_CLK
  2018-06-01  6:58   ` Oleksij Rempel
  (?)
@ 2018-06-13 10:38     ` Dong Aisheng
  -1 siblings, 0 replies; 54+ messages in thread
From: Dong Aisheng @ 2018-06-13 10:38 UTC (permalink / raw)
  To: Oleksij Rempel
  Cc: Mark Rutland, devicetree, Rob Herring, dl-linux-imx,
	Sascha Hauer, Dong Aisheng, Fabio Estevam, Shawn Guo, linux-clk,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE

On Fri, Jun 1, 2018 at 2:58 PM, Oleksij Rempel <o.rempel@pengutronix.de> wrote:
> This clock is needed for iMX mailbox driver
>
> Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
> ---
>  drivers/clk/imx/clk-imx7d.c | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/drivers/clk/imx/clk-imx7d.c b/drivers/clk/imx/clk-imx7d.c
> index 975a20d3cc94..1c2541dc40e7 100644
> --- a/drivers/clk/imx/clk-imx7d.c
> +++ b/drivers/clk/imx/clk-imx7d.c
> @@ -793,6 +793,7 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
>         clks[IMX7D_DRAM_PHYM_ROOT_CLK] = imx_clk_gate4("dram_phym_root_clk", "dram_phym_cg", base + 0x4130, 0);
>         clks[IMX7D_DRAM_PHYM_ALT_ROOT_CLK] = imx_clk_gate4("dram_phym_alt_root_clk", "dram_phym_alt_post_div", base + 0x4130, 0);
>         clks[IMX7D_DRAM_ALT_ROOT_CLK] = imx_clk_gate4("dram_alt_root_clk", "dram_alt_post_div", base + 0x4130, 0);
> +       clks[IMX7D_MU_ROOT_CLK] = imx_clk_gate2("mu_root_clk", "ipg_root_clk", base + 0x4270, 0);

The clock slice on MX7D needs to operate while its parent clock is on.
So this seems ought to be imx_clk_gate4?

Besides that, a nitpick:
although the address is already out of order, but we are still better to keep
in increasing order as long as we can.

Regards
Dong Aisheng

>         clks[IMX7D_OCOTP_CLK] = imx_clk_gate4("ocotp_clk", "ipg_root_clk", base + 0x4230, 0);
>         clks[IMX7D_SNVS_CLK] = imx_clk_gate4("snvs_clk", "ipg_root_clk", base + 0x4250, 0);
>         clks[IMX7D_CAAM_CLK] = imx_clk_gate4("caam_clk", "ipg_root_clk", base + 0x4240, 0);
> --
> 2.17.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-clk" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v1 1/4] clk: imx7d: add IMX7D_MU_ROOT_CLK
@ 2018-06-13 10:38     ` Dong Aisheng
  0 siblings, 0 replies; 54+ messages in thread
From: Dong Aisheng @ 2018-06-13 10:38 UTC (permalink / raw)
  To: Oleksij Rempel
  Cc: Shawn Guo, Fabio Estevam, Rob Herring, Mark Rutland,
	Sascha Hauer,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
	devicetree, linux-clk, dl-linux-imx, Dong Aisheng

On Fri, Jun 1, 2018 at 2:58 PM, Oleksij Rempel <o.rempel@pengutronix.de> wrote:
> This clock is needed for iMX mailbox driver
>
> Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
> ---
>  drivers/clk/imx/clk-imx7d.c | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/drivers/clk/imx/clk-imx7d.c b/drivers/clk/imx/clk-imx7d.c
> index 975a20d3cc94..1c2541dc40e7 100644
> --- a/drivers/clk/imx/clk-imx7d.c
> +++ b/drivers/clk/imx/clk-imx7d.c
> @@ -793,6 +793,7 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
>         clks[IMX7D_DRAM_PHYM_ROOT_CLK] = imx_clk_gate4("dram_phym_root_clk", "dram_phym_cg", base + 0x4130, 0);
>         clks[IMX7D_DRAM_PHYM_ALT_ROOT_CLK] = imx_clk_gate4("dram_phym_alt_root_clk", "dram_phym_alt_post_div", base + 0x4130, 0);
>         clks[IMX7D_DRAM_ALT_ROOT_CLK] = imx_clk_gate4("dram_alt_root_clk", "dram_alt_post_div", base + 0x4130, 0);
> +       clks[IMX7D_MU_ROOT_CLK] = imx_clk_gate2("mu_root_clk", "ipg_root_clk", base + 0x4270, 0);

The clock slice on MX7D needs to operate while its parent clock is on.
So this seems ought to be imx_clk_gate4?

Besides that, a nitpick:
although the address is already out of order, but we are still better to keep
in increasing order as long as we can.

Regards
Dong Aisheng

>         clks[IMX7D_OCOTP_CLK] = imx_clk_gate4("ocotp_clk", "ipg_root_clk", base + 0x4230, 0);
>         clks[IMX7D_SNVS_CLK] = imx_clk_gate4("snvs_clk", "ipg_root_clk", base + 0x4250, 0);
>         clks[IMX7D_CAAM_CLK] = imx_clk_gate4("caam_clk", "ipg_root_clk", base + 0x4240, 0);
> --
> 2.17.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-clk" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 54+ messages in thread

* [PATCH v1 1/4] clk: imx7d: add IMX7D_MU_ROOT_CLK
@ 2018-06-13 10:38     ` Dong Aisheng
  0 siblings, 0 replies; 54+ messages in thread
From: Dong Aisheng @ 2018-06-13 10:38 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Jun 1, 2018 at 2:58 PM, Oleksij Rempel <o.rempel@pengutronix.de> wrote:
> This clock is needed for iMX mailbox driver
>
> Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
> ---
>  drivers/clk/imx/clk-imx7d.c | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/drivers/clk/imx/clk-imx7d.c b/drivers/clk/imx/clk-imx7d.c
> index 975a20d3cc94..1c2541dc40e7 100644
> --- a/drivers/clk/imx/clk-imx7d.c
> +++ b/drivers/clk/imx/clk-imx7d.c
> @@ -793,6 +793,7 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
>         clks[IMX7D_DRAM_PHYM_ROOT_CLK] = imx_clk_gate4("dram_phym_root_clk", "dram_phym_cg", base + 0x4130, 0);
>         clks[IMX7D_DRAM_PHYM_ALT_ROOT_CLK] = imx_clk_gate4("dram_phym_alt_root_clk", "dram_phym_alt_post_div", base + 0x4130, 0);
>         clks[IMX7D_DRAM_ALT_ROOT_CLK] = imx_clk_gate4("dram_alt_root_clk", "dram_alt_post_div", base + 0x4130, 0);
> +       clks[IMX7D_MU_ROOT_CLK] = imx_clk_gate2("mu_root_clk", "ipg_root_clk", base + 0x4270, 0);

The clock slice on MX7D needs to operate while its parent clock is on.
So this seems ought to be imx_clk_gate4?

Besides that, a nitpick:
although the address is already out of order, but we are still better to keep
in increasing order as long as we can.

Regards
Dong Aisheng

>         clks[IMX7D_OCOTP_CLK] = imx_clk_gate4("ocotp_clk", "ipg_root_clk", base + 0x4230, 0);
>         clks[IMX7D_SNVS_CLK] = imx_clk_gate4("snvs_clk", "ipg_root_clk", base + 0x4250, 0);
>         clks[IMX7D_CAAM_CLK] = imx_clk_gate4("caam_clk", "ipg_root_clk", base + 0x4240, 0);
> --
> 2.17.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-clk" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v1 2/4] dt-bindings: mailbox: provide imx-mailbox documentation
  2018-06-01  6:58   ` Oleksij Rempel
  (?)
@ 2018-06-13 11:05     ` Dong Aisheng
  -1 siblings, 0 replies; 54+ messages in thread
From: Dong Aisheng @ 2018-06-13 11:05 UTC (permalink / raw)
  To: Oleksij Rempel
  Cc: Mark Rutland, devicetree, Rob Herring, Sascha Hauer,
	Fabio Estevam, Shawn Guo, linux-clk,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE

Hi Oleksij,

Some more comments besides Rob's:

On Fri, Jun 1, 2018 at 2:58 PM, Oleksij Rempel <o.rempel@pengutronix.de> wrote:
> Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
> ---
>  .../bindings/mailbox/imx-mailbox.txt          | 35 +++++++++++++++++++
>  1 file changed, 35 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mailbox/imx-mailbox.txt
>
> diff --git a/Documentation/devicetree/bindings/mailbox/imx-mailbox.txt b/Documentation/devicetree/bindings/mailbox/imx-mailbox.txt
> new file mode 100644
> index 000000000000..a45604b33039
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mailbox/imx-mailbox.txt
> @@ -0,0 +1,35 @@
> +i.MX Messaging Unit
> +===================
> +
> +The i.MX Messaging Unit (MU) contains two register sets: "A" and "B". In most cases
> +they are accessible from all Processor Units. On one hand, at least for mailbox functionality,
> +it makes no difference which application or processor is using which set of the MU. On
> +other hand, the register sets for each of the MU parts are not identical.
> +
> +Required properties:
> +- compatible : Shell be one of:
> +                    "fsl,imx7s-mu-a" and "fsl,imx7s-mu-b" for i.MX7S or i.MX7D

What's current requirement to distinguish Side A and B?
I see current code, side A only does extra clear of xCR register but none for B.
Is this a generic approach or something customized?

BTW can we name it more generically?e.g. fsl,imx7s-mu.
And using a property to indicate whether it's side A or B if really required.

Furthermore, AFAIK MX7 MU is derived from MX6SX.
Should we add and use fsl,imx6sx-mu instead?
e.g.
 - compatible : Shell be one of:
                       "fsl,imx6sx-mu" and "fsl,imx7s-mu".

Regards
Dong Aisheng

> +- reg :        physical base address of the mailbox and length of
> +               memory mapped region.
> +- #mbox-cells: Common mailbox binding property to identify the number
> +               of cells required for the mailbox specifier. Should be 1.
> +- interrupts : interrupt number. The interrupt specifier format
> +               depends on the interrupt controller parent.
> +- clocks     :  phandle to the input clock.
> +
> +Example:
> +       mu0a: mu@30aa0000 {
> +               compatible = "fsl,imx7s-mu-a";
> +               reg = <0x30aa0000 0x28>;
> +               interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
> +               clocks = <&clks IMX7D_MU_ROOT_CLK>;
> +               #mbox-cells = <1>;
> +       };
> +
> +       mu0b: mu@30ab0000 {
> +               compatible = "fsl,imx7s-mu-b";
> +               reg = <0x30ab0000 0x28>;
> +               interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
> +               clocks = <&clks IMX7D_MU_ROOT_CLK>;
> +               #mbox-cells = <1>;
> +       };
> --
> 2.17.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-clk" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v1 2/4] dt-bindings: mailbox: provide imx-mailbox documentation
@ 2018-06-13 11:05     ` Dong Aisheng
  0 siblings, 0 replies; 54+ messages in thread
From: Dong Aisheng @ 2018-06-13 11:05 UTC (permalink / raw)
  To: Oleksij Rempel
  Cc: Shawn Guo, Fabio Estevam, Rob Herring, Mark Rutland,
	Sascha Hauer,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
	devicetree, linux-clk

Hi Oleksij,

Some more comments besides Rob's:

On Fri, Jun 1, 2018 at 2:58 PM, Oleksij Rempel <o.rempel@pengutronix.de> wrote:
> Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
> ---
>  .../bindings/mailbox/imx-mailbox.txt          | 35 +++++++++++++++++++
>  1 file changed, 35 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mailbox/imx-mailbox.txt
>
> diff --git a/Documentation/devicetree/bindings/mailbox/imx-mailbox.txt b/Documentation/devicetree/bindings/mailbox/imx-mailbox.txt
> new file mode 100644
> index 000000000000..a45604b33039
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mailbox/imx-mailbox.txt
> @@ -0,0 +1,35 @@
> +i.MX Messaging Unit
> +===================
> +
> +The i.MX Messaging Unit (MU) contains two register sets: "A" and "B". In most cases
> +they are accessible from all Processor Units. On one hand, at least for mailbox functionality,
> +it makes no difference which application or processor is using which set of the MU. On
> +other hand, the register sets for each of the MU parts are not identical.
> +
> +Required properties:
> +- compatible : Shell be one of:
> +                    "fsl,imx7s-mu-a" and "fsl,imx7s-mu-b" for i.MX7S or i.MX7D

What's current requirement to distinguish Side A and B?
I see current code, side A only does extra clear of xCR register but none for B.
Is this a generic approach or something customized?

BTW can we name it more generically?e.g. fsl,imx7s-mu.
And using a property to indicate whether it's side A or B if really required.

Furthermore, AFAIK MX7 MU is derived from MX6SX.
Should we add and use fsl,imx6sx-mu instead?
e.g.
 - compatible : Shell be one of:
                       "fsl,imx6sx-mu" and "fsl,imx7s-mu".

Regards
Dong Aisheng

> +- reg :        physical base address of the mailbox and length of
> +               memory mapped region.
> +- #mbox-cells: Common mailbox binding property to identify the number
> +               of cells required for the mailbox specifier. Should be 1.
> +- interrupts : interrupt number. The interrupt specifier format
> +               depends on the interrupt controller parent.
> +- clocks     :  phandle to the input clock.
> +
> +Example:
> +       mu0a: mu@30aa0000 {
> +               compatible = "fsl,imx7s-mu-a";
> +               reg = <0x30aa0000 0x28>;
> +               interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
> +               clocks = <&clks IMX7D_MU_ROOT_CLK>;
> +               #mbox-cells = <1>;
> +       };
> +
> +       mu0b: mu@30ab0000 {
> +               compatible = "fsl,imx7s-mu-b";
> +               reg = <0x30ab0000 0x28>;
> +               interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
> +               clocks = <&clks IMX7D_MU_ROOT_CLK>;
> +               #mbox-cells = <1>;
> +       };
> --
> 2.17.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-clk" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 54+ messages in thread

* [PATCH v1 2/4] dt-bindings: mailbox: provide imx-mailbox documentation
@ 2018-06-13 11:05     ` Dong Aisheng
  0 siblings, 0 replies; 54+ messages in thread
From: Dong Aisheng @ 2018-06-13 11:05 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Oleksij,

Some more comments besides Rob's:

On Fri, Jun 1, 2018 at 2:58 PM, Oleksij Rempel <o.rempel@pengutronix.de> wrote:
> Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
> ---
>  .../bindings/mailbox/imx-mailbox.txt          | 35 +++++++++++++++++++
>  1 file changed, 35 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mailbox/imx-mailbox.txt
>
> diff --git a/Documentation/devicetree/bindings/mailbox/imx-mailbox.txt b/Documentation/devicetree/bindings/mailbox/imx-mailbox.txt
> new file mode 100644
> index 000000000000..a45604b33039
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mailbox/imx-mailbox.txt
> @@ -0,0 +1,35 @@
> +i.MX Messaging Unit
> +===================
> +
> +The i.MX Messaging Unit (MU) contains two register sets: "A" and "B". In most cases
> +they are accessible from all Processor Units. On one hand, at least for mailbox functionality,
> +it makes no difference which application or processor is using which set of the MU. On
> +other hand, the register sets for each of the MU parts are not identical.
> +
> +Required properties:
> +- compatible : Shell be one of:
> +                    "fsl,imx7s-mu-a" and "fsl,imx7s-mu-b" for i.MX7S or i.MX7D

What's current requirement to distinguish Side A and B?
I see current code, side A only does extra clear of xCR register but none for B.
Is this a generic approach or something customized?

BTW can we name it more generically?e.g. fsl,imx7s-mu.
And using a property to indicate whether it's side A or B if really required.

Furthermore, AFAIK MX7 MU is derived from MX6SX.
Should we add and use fsl,imx6sx-mu instead?
e.g.
 - compatible : Shell be one of:
                       "fsl,imx6sx-mu" and "fsl,imx7s-mu".

Regards
Dong Aisheng

> +- reg :        physical base address of the mailbox and length of
> +               memory mapped region.
> +- #mbox-cells: Common mailbox binding property to identify the number
> +               of cells required for the mailbox specifier. Should be 1.
> +- interrupts : interrupt number. The interrupt specifier format
> +               depends on the interrupt controller parent.
> +- clocks     :  phandle to the input clock.
> +
> +Example:
> +       mu0a: mu at 30aa0000 {
> +               compatible = "fsl,imx7s-mu-a";
> +               reg = <0x30aa0000 0x28>;
> +               interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
> +               clocks = <&clks IMX7D_MU_ROOT_CLK>;
> +               #mbox-cells = <1>;
> +       };
> +
> +       mu0b: mu at 30ab0000 {
> +               compatible = "fsl,imx7s-mu-b";
> +               reg = <0x30ab0000 0x28>;
> +               interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
> +               clocks = <&clks IMX7D_MU_ROOT_CLK>;
> +               #mbox-cells = <1>;
> +       };
> --
> 2.17.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-clk" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v1 2/4] dt-bindings: mailbox: provide imx-mailbox documentation
  2018-06-13 11:05     ` Dong Aisheng
  (?)
@ 2018-06-13 11:58       ` Oleksij Rempel
  -1 siblings, 0 replies; 54+ messages in thread
From: Oleksij Rempel @ 2018-06-13 11:58 UTC (permalink / raw)
  To: Dong Aisheng
  Cc: Mark Rutland, devicetree, Rob Herring, Sascha Hauer,
	Fabio Estevam, Shawn Guo, linux-clk,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE


[-- Attachment #1.1.1: Type: text/plain, Size: 3607 bytes --]



On 13.06.2018 13:05, Dong Aisheng wrote:
> Hi Oleksij,
> 
> Some more comments besides Rob's:
> 
> On Fri, Jun 1, 2018 at 2:58 PM, Oleksij Rempel <o.rempel@pengutronix.de> wrote:
>> Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
>> ---
>>  .../bindings/mailbox/imx-mailbox.txt          | 35 +++++++++++++++++++
>>  1 file changed, 35 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/mailbox/imx-mailbox.txt
>>
>> diff --git a/Documentation/devicetree/bindings/mailbox/imx-mailbox.txt b/Documentation/devicetree/bindings/mailbox/imx-mailbox.txt
>> new file mode 100644
>> index 000000000000..a45604b33039
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/mailbox/imx-mailbox.txt
>> @@ -0,0 +1,35 @@
>> +i.MX Messaging Unit
>> +===================
>> +
>> +The i.MX Messaging Unit (MU) contains two register sets: "A" and "B". In most cases
>> +they are accessible from all Processor Units. On one hand, at least for mailbox functionality,
>> +it makes no difference which application or processor is using which set of the MU. On
>> +other hand, the register sets for each of the MU parts are not identical.
>> +
>> +Required properties:
>> +- compatible : Shell be one of:
>> +                    "fsl,imx7s-mu-a" and "fsl,imx7s-mu-b" for i.MX7S or i.MX7D
> 
> What's current requirement to distinguish Side A and B?
> I see current code, side A only does extra clear of xCR register but none for B.
> Is this a generic approach or something customized?

A and B side have more then one BIT difference, and there is no way to
see the difference by software. Current driver do not make use of it,
but in devicetree we describe HW not SW. If HW is different, it should
have different compatibles.

> BTW can we name it more generically?e.g. fsl,imx7s-mu.
> And using a property to indicate whether it's side A or B if really required.
> 
> Furthermore, AFAIK MX7 MU is derived from MX6SX.
> Should we add and use fsl,imx6sx-mu instead?

As soon as some one will test this driver on imx6sx and confirm it
working, i'll add fsl,imx6sx-mu-a/b as well.

> e.g.
>  - compatible : Shell be one of:
>                        "fsl,imx6sx-mu" and "fsl,imx7s-mu".
> 
> Regards
> Dong Aisheng
> 
>> +- reg :        physical base address of the mailbox and length of
>> +               memory mapped region.
>> +- #mbox-cells: Common mailbox binding property to identify the number
>> +               of cells required for the mailbox specifier. Should be 1.
>> +- interrupts : interrupt number. The interrupt specifier format
>> +               depends on the interrupt controller parent.
>> +- clocks     :  phandle to the input clock.
>> +
>> +Example:
>> +       mu0a: mu@30aa0000 {
>> +               compatible = "fsl,imx7s-mu-a";
>> +               reg = <0x30aa0000 0x28>;
>> +               interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
>> +               clocks = <&clks IMX7D_MU_ROOT_CLK>;
>> +               #mbox-cells = <1>;
>> +       };
>> +
>> +       mu0b: mu@30ab0000 {
>> +               compatible = "fsl,imx7s-mu-b";
>> +               reg = <0x30ab0000 0x28>;
>> +               interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
>> +               clocks = <&clks IMX7D_MU_ROOT_CLK>;
>> +               #mbox-cells = <1>;
>> +       };
>> --
>> 2.17.1
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-clk" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
> 


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

[-- Attachment #2: Type: text/plain, Size: 176 bytes --]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v1 2/4] dt-bindings: mailbox: provide imx-mailbox documentation
@ 2018-06-13 11:58       ` Oleksij Rempel
  0 siblings, 0 replies; 54+ messages in thread
From: Oleksij Rempel @ 2018-06-13 11:58 UTC (permalink / raw)
  To: Dong Aisheng
  Cc: Mark Rutland, devicetree, Rob Herring, Sascha Hauer,
	Fabio Estevam, Shawn Guo, linux-clk,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE


[-- Attachment #1.1: Type: text/plain, Size: 3607 bytes --]



On 13.06.2018 13:05, Dong Aisheng wrote:
> Hi Oleksij,
> 
> Some more comments besides Rob's:
> 
> On Fri, Jun 1, 2018 at 2:58 PM, Oleksij Rempel <o.rempel@pengutronix.de> wrote:
>> Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
>> ---
>>  .../bindings/mailbox/imx-mailbox.txt          | 35 +++++++++++++++++++
>>  1 file changed, 35 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/mailbox/imx-mailbox.txt
>>
>> diff --git a/Documentation/devicetree/bindings/mailbox/imx-mailbox.txt b/Documentation/devicetree/bindings/mailbox/imx-mailbox.txt
>> new file mode 100644
>> index 000000000000..a45604b33039
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/mailbox/imx-mailbox.txt
>> @@ -0,0 +1,35 @@
>> +i.MX Messaging Unit
>> +===================
>> +
>> +The i.MX Messaging Unit (MU) contains two register sets: "A" and "B". In most cases
>> +they are accessible from all Processor Units. On one hand, at least for mailbox functionality,
>> +it makes no difference which application or processor is using which set of the MU. On
>> +other hand, the register sets for each of the MU parts are not identical.
>> +
>> +Required properties:
>> +- compatible : Shell be one of:
>> +                    "fsl,imx7s-mu-a" and "fsl,imx7s-mu-b" for i.MX7S or i.MX7D
> 
> What's current requirement to distinguish Side A and B?
> I see current code, side A only does extra clear of xCR register but none for B.
> Is this a generic approach or something customized?

A and B side have more then one BIT difference, and there is no way to
see the difference by software. Current driver do not make use of it,
but in devicetree we describe HW not SW. If HW is different, it should
have different compatibles.

> BTW can we name it more generically?e.g. fsl,imx7s-mu.
> And using a property to indicate whether it's side A or B if really required.
> 
> Furthermore, AFAIK MX7 MU is derived from MX6SX.
> Should we add and use fsl,imx6sx-mu instead?

As soon as some one will test this driver on imx6sx and confirm it
working, i'll add fsl,imx6sx-mu-a/b as well.

> e.g.
>  - compatible : Shell be one of:
>                        "fsl,imx6sx-mu" and "fsl,imx7s-mu".
> 
> Regards
> Dong Aisheng
> 
>> +- reg :        physical base address of the mailbox and length of
>> +               memory mapped region.
>> +- #mbox-cells: Common mailbox binding property to identify the number
>> +               of cells required for the mailbox specifier. Should be 1.
>> +- interrupts : interrupt number. The interrupt specifier format
>> +               depends on the interrupt controller parent.
>> +- clocks     :  phandle to the input clock.
>> +
>> +Example:
>> +       mu0a: mu@30aa0000 {
>> +               compatible = "fsl,imx7s-mu-a";
>> +               reg = <0x30aa0000 0x28>;
>> +               interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
>> +               clocks = <&clks IMX7D_MU_ROOT_CLK>;
>> +               #mbox-cells = <1>;
>> +       };
>> +
>> +       mu0b: mu@30ab0000 {
>> +               compatible = "fsl,imx7s-mu-b";
>> +               reg = <0x30ab0000 0x28>;
>> +               interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
>> +               clocks = <&clks IMX7D_MU_ROOT_CLK>;
>> +               #mbox-cells = <1>;
>> +       };
>> --
>> 2.17.1
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-clk" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
> 


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 54+ messages in thread

* [PATCH v1 2/4] dt-bindings: mailbox: provide imx-mailbox documentation
@ 2018-06-13 11:58       ` Oleksij Rempel
  0 siblings, 0 replies; 54+ messages in thread
From: Oleksij Rempel @ 2018-06-13 11:58 UTC (permalink / raw)
  To: linux-arm-kernel



On 13.06.2018 13:05, Dong Aisheng wrote:
> Hi Oleksij,
> 
> Some more comments besides Rob's:
> 
> On Fri, Jun 1, 2018 at 2:58 PM, Oleksij Rempel <o.rempel@pengutronix.de> wrote:
>> Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
>> ---
>>  .../bindings/mailbox/imx-mailbox.txt          | 35 +++++++++++++++++++
>>  1 file changed, 35 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/mailbox/imx-mailbox.txt
>>
>> diff --git a/Documentation/devicetree/bindings/mailbox/imx-mailbox.txt b/Documentation/devicetree/bindings/mailbox/imx-mailbox.txt
>> new file mode 100644
>> index 000000000000..a45604b33039
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/mailbox/imx-mailbox.txt
>> @@ -0,0 +1,35 @@
>> +i.MX Messaging Unit
>> +===================
>> +
>> +The i.MX Messaging Unit (MU) contains two register sets: "A" and "B". In most cases
>> +they are accessible from all Processor Units. On one hand, at least for mailbox functionality,
>> +it makes no difference which application or processor is using which set of the MU. On
>> +other hand, the register sets for each of the MU parts are not identical.
>> +
>> +Required properties:
>> +- compatible : Shell be one of:
>> +                    "fsl,imx7s-mu-a" and "fsl,imx7s-mu-b" for i.MX7S or i.MX7D
> 
> What's current requirement to distinguish Side A and B?
> I see current code, side A only does extra clear of xCR register but none for B.
> Is this a generic approach or something customized?

A and B side have more then one BIT difference, and there is no way to
see the difference by software. Current driver do not make use of it,
but in devicetree we describe HW not SW. If HW is different, it should
have different compatibles.

> BTW can we name it more generically?e.g. fsl,imx7s-mu.
> And using a property to indicate whether it's side A or B if really required.
> 
> Furthermore, AFAIK MX7 MU is derived from MX6SX.
> Should we add and use fsl,imx6sx-mu instead?

As soon as some one will test this driver on imx6sx and confirm it
working, i'll add fsl,imx6sx-mu-a/b as well.

> e.g.
>  - compatible : Shell be one of:
>                        "fsl,imx6sx-mu" and "fsl,imx7s-mu".
> 
> Regards
> Dong Aisheng
> 
>> +- reg :        physical base address of the mailbox and length of
>> +               memory mapped region.
>> +- #mbox-cells: Common mailbox binding property to identify the number
>> +               of cells required for the mailbox specifier. Should be 1.
>> +- interrupts : interrupt number. The interrupt specifier format
>> +               depends on the interrupt controller parent.
>> +- clocks     :  phandle to the input clock.
>> +
>> +Example:
>> +       mu0a: mu at 30aa0000 {
>> +               compatible = "fsl,imx7s-mu-a";
>> +               reg = <0x30aa0000 0x28>;
>> +               interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
>> +               clocks = <&clks IMX7D_MU_ROOT_CLK>;
>> +               #mbox-cells = <1>;
>> +       };
>> +
>> +       mu0b: mu at 30ab0000 {
>> +               compatible = "fsl,imx7s-mu-b";
>> +               reg = <0x30ab0000 0x28>;
>> +               interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
>> +               clocks = <&clks IMX7D_MU_ROOT_CLK>;
>> +               #mbox-cells = <1>;
>> +       };
>> --
>> 2.17.1
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-clk" in
>> the body of a message to majordomo at vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
> 

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180613/a91c9c57/attachment-0001.sig>

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v1 2/4] dt-bindings: mailbox: provide imx-mailbox documentation
  2018-06-12 19:41     ` Rob Herring
  (?)
@ 2018-06-13 11:59       ` Oleksij Rempel
  -1 siblings, 0 replies; 54+ messages in thread
From: Oleksij Rempel @ 2018-06-13 11:59 UTC (permalink / raw)
  To: Rob Herring
  Cc: Mark Rutland, devicetree, kernel, Fabio Estevam, Shawn Guo,
	linux-clk, linux-arm-kernel


[-- Attachment #1.1.1: Type: text/plain, Size: 2368 bytes --]



On 12.06.2018 21:41, Rob Herring wrote:
> On Fri, Jun 01, 2018 at 08:58:19AM +0200, Oleksij Rempel wrote:
>> Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
>> ---
>>  .../bindings/mailbox/imx-mailbox.txt          | 35 +++++++++++++++++++
>>  1 file changed, 35 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/mailbox/imx-mailbox.txt
>>
>> diff --git a/Documentation/devicetree/bindings/mailbox/imx-mailbox.txt b/Documentation/devicetree/bindings/mailbox/imx-mailbox.txt
>> new file mode 100644
>> index 000000000000..a45604b33039
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/mailbox/imx-mailbox.txt
>> @@ -0,0 +1,35 @@
>> +i.MX Messaging Unit
>> +===================
>> +
>> +The i.MX Messaging Unit (MU) contains two register sets: "A" and "B". In most cases
>> +they are accessible from all Processor Units. On one hand, at least for mailbox functionality,
>> +it makes no difference which application or processor is using which set of the MU. On
> 
> Please wrap lines correctly (<80).
> 
>> +other hand, the register sets for each of the MU parts are not identical.
>> +
>> +Required properties:
>> +- compatible :	Shell be one of:
>> +                    "fsl,imx7s-mu-a" and "fsl,imx7s-mu-b" for i.MX7S or i.MX7D
>> +- reg : 	physical base address of the mailbox and length of
> 
> Mix of space and tab.
> 
>> +		memory mapped region.
>> +- #mbox-cells:	Common mailbox binding property to identify the number
>> +		of cells required for the mailbox specifier. Should be 1.
>> +- interrupts :	interrupt number. The interrupt specifier format
>> +		depends on the interrupt controller parent.
> 
> Just need to say how many interrupts and what they are if more than 1.
> 
>> +- clocks     :  phandle to the input clock.
>> +
>> +Example:
>> +	mu0a: mu@30aa0000 {
> 
> mailbox@...
> 
>> +		compatible = "fsl,imx7s-mu-a";
>> +		reg = <0x30aa0000 0x28>;
>> +		interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
>> +		clocks = <&clks IMX7D_MU_ROOT_CLK>;
>> +		#mbox-cells = <1>;
>> +	};
>> +
>> +	mu0b: mu@30ab0000 {
> 
> mailbox@...
> 
>> +		compatible = "fsl,imx7s-mu-b";
>> +		reg = <0x30ab0000 0x28>;
>> +		interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
>> +		clocks = <&clks IMX7D_MU_ROOT_CLK>;
>> +		#mbox-cells = <1>;
>> +	};

thx. will fix it.


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

[-- Attachment #2: Type: text/plain, Size: 176 bytes --]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v1 2/4] dt-bindings: mailbox: provide imx-mailbox documentation
@ 2018-06-13 11:59       ` Oleksij Rempel
  0 siblings, 0 replies; 54+ messages in thread
From: Oleksij Rempel @ 2018-06-13 11:59 UTC (permalink / raw)
  To: Rob Herring
  Cc: Mark Rutland, devicetree, kernel, Fabio Estevam, Shawn Guo,
	linux-clk, linux-arm-kernel


[-- Attachment #1.1: Type: text/plain, Size: 2368 bytes --]



On 12.06.2018 21:41, Rob Herring wrote:
> On Fri, Jun 01, 2018 at 08:58:19AM +0200, Oleksij Rempel wrote:
>> Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
>> ---
>>  .../bindings/mailbox/imx-mailbox.txt          | 35 +++++++++++++++++++
>>  1 file changed, 35 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/mailbox/imx-mailbox.txt
>>
>> diff --git a/Documentation/devicetree/bindings/mailbox/imx-mailbox.txt b/Documentation/devicetree/bindings/mailbox/imx-mailbox.txt
>> new file mode 100644
>> index 000000000000..a45604b33039
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/mailbox/imx-mailbox.txt
>> @@ -0,0 +1,35 @@
>> +i.MX Messaging Unit
>> +===================
>> +
>> +The i.MX Messaging Unit (MU) contains two register sets: "A" and "B". In most cases
>> +they are accessible from all Processor Units. On one hand, at least for mailbox functionality,
>> +it makes no difference which application or processor is using which set of the MU. On
> 
> Please wrap lines correctly (<80).
> 
>> +other hand, the register sets for each of the MU parts are not identical.
>> +
>> +Required properties:
>> +- compatible :	Shell be one of:
>> +                    "fsl,imx7s-mu-a" and "fsl,imx7s-mu-b" for i.MX7S or i.MX7D
>> +- reg : 	physical base address of the mailbox and length of
> 
> Mix of space and tab.
> 
>> +		memory mapped region.
>> +- #mbox-cells:	Common mailbox binding property to identify the number
>> +		of cells required for the mailbox specifier. Should be 1.
>> +- interrupts :	interrupt number. The interrupt specifier format
>> +		depends on the interrupt controller parent.
> 
> Just need to say how many interrupts and what they are if more than 1.
> 
>> +- clocks     :  phandle to the input clock.
>> +
>> +Example:
>> +	mu0a: mu@30aa0000 {
> 
> mailbox@...
> 
>> +		compatible = "fsl,imx7s-mu-a";
>> +		reg = <0x30aa0000 0x28>;
>> +		interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
>> +		clocks = <&clks IMX7D_MU_ROOT_CLK>;
>> +		#mbox-cells = <1>;
>> +	};
>> +
>> +	mu0b: mu@30ab0000 {
> 
> mailbox@...
> 
>> +		compatible = "fsl,imx7s-mu-b";
>> +		reg = <0x30ab0000 0x28>;
>> +		interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
>> +		clocks = <&clks IMX7D_MU_ROOT_CLK>;
>> +		#mbox-cells = <1>;
>> +	};

thx. will fix it.


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 54+ messages in thread

* [PATCH v1 2/4] dt-bindings: mailbox: provide imx-mailbox documentation
@ 2018-06-13 11:59       ` Oleksij Rempel
  0 siblings, 0 replies; 54+ messages in thread
From: Oleksij Rempel @ 2018-06-13 11:59 UTC (permalink / raw)
  To: linux-arm-kernel



On 12.06.2018 21:41, Rob Herring wrote:
> On Fri, Jun 01, 2018 at 08:58:19AM +0200, Oleksij Rempel wrote:
>> Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
>> ---
>>  .../bindings/mailbox/imx-mailbox.txt          | 35 +++++++++++++++++++
>>  1 file changed, 35 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/mailbox/imx-mailbox.txt
>>
>> diff --git a/Documentation/devicetree/bindings/mailbox/imx-mailbox.txt b/Documentation/devicetree/bindings/mailbox/imx-mailbox.txt
>> new file mode 100644
>> index 000000000000..a45604b33039
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/mailbox/imx-mailbox.txt
>> @@ -0,0 +1,35 @@
>> +i.MX Messaging Unit
>> +===================
>> +
>> +The i.MX Messaging Unit (MU) contains two register sets: "A" and "B". In most cases
>> +they are accessible from all Processor Units. On one hand, at least for mailbox functionality,
>> +it makes no difference which application or processor is using which set of the MU. On
> 
> Please wrap lines correctly (<80).
> 
>> +other hand, the register sets for each of the MU parts are not identical.
>> +
>> +Required properties:
>> +- compatible :	Shell be one of:
>> +                    "fsl,imx7s-mu-a" and "fsl,imx7s-mu-b" for i.MX7S or i.MX7D
>> +- reg : 	physical base address of the mailbox and length of
> 
> Mix of space and tab.
> 
>> +		memory mapped region.
>> +- #mbox-cells:	Common mailbox binding property to identify the number
>> +		of cells required for the mailbox specifier. Should be 1.
>> +- interrupts :	interrupt number. The interrupt specifier format
>> +		depends on the interrupt controller parent.
> 
> Just need to say how many interrupts and what they are if more than 1.
> 
>> +- clocks     :  phandle to the input clock.
>> +
>> +Example:
>> +	mu0a: mu at 30aa0000 {
> 
> mailbox at ...
> 
>> +		compatible = "fsl,imx7s-mu-a";
>> +		reg = <0x30aa0000 0x28>;
>> +		interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
>> +		clocks = <&clks IMX7D_MU_ROOT_CLK>;
>> +		#mbox-cells = <1>;
>> +	};
>> +
>> +	mu0b: mu at 30ab0000 {
> 
> mailbox at ...
> 
>> +		compatible = "fsl,imx7s-mu-b";
>> +		reg = <0x30ab0000 0x28>;
>> +		interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
>> +		clocks = <&clks IMX7D_MU_ROOT_CLK>;
>> +		#mbox-cells = <1>;
>> +	};

thx. will fix it.

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180613/3d9a7f9d/attachment.sig>

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v1 4/4] mailbox: Add support for i.MX7D messaging unit
  2018-06-01  6:58   ` Oleksij Rempel
  (?)
@ 2018-06-13 12:21     ` Dong Aisheng
  -1 siblings, 0 replies; 54+ messages in thread
From: Dong Aisheng @ 2018-06-13 12:21 UTC (permalink / raw)
  To: Oleksij Rempel
  Cc: Mark Rutland, devicetree, Rob Herring, Sascha Hauer,
	Fabio Estevam, Shawn Guo, linux-clk,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE

Hi Oleksij,

On Fri, Jun 1, 2018 at 2:58 PM, Oleksij Rempel <o.rempel@pengutronix.de> wrote:
> The Mailbox controller is able to send messages (up to 4 32 bit words)
> between the endpoints.

Could we really be able to send up to 4 42bit words with this driver?

It looks to me the current Mailbox framework is more designed for share mem
transfer which does not fit i.MX MU well.

>
> This driver was tested using the mailbox-test driver sending messages
> between the Cortex-A7 and the Cortex-M4.

Would you please provide a guide on how to test it quickly?
I may want to give a test.

>
> Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
> ---
>  drivers/mailbox/Kconfig       |   6 +
>  drivers/mailbox/Makefile      |   2 +
>  drivers/mailbox/imx-mailbox.c | 289 ++++++++++++++++++++++++++++++++++
>  3 files changed, 297 insertions(+)
>  create mode 100644 drivers/mailbox/imx-mailbox.c
>
> diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
> index a2bb27446dce..e1d2738a2e4c 100644
> --- a/drivers/mailbox/Kconfig
> +++ b/drivers/mailbox/Kconfig
> @@ -15,6 +15,12 @@ config ARM_MHU
>           The controller has 3 mailbox channels, the last of which can be
>           used in Secure mode only.
>
> +config IMX_MBOX
> +       tristate "iMX Mailbox"
> +       depends on SOC_IMX7D || COMPILE_TEST
> +       help
> +         Mailbox implementation for iMX7D Messaging Unit (MU).
> +
>  config PLATFORM_MHU
>         tristate "Platform MHU Mailbox"
>         depends on OF
> diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
> index cc23c3a43fcd..ba2fe1b6dd62 100644
> --- a/drivers/mailbox/Makefile
> +++ b/drivers/mailbox/Makefile
> @@ -7,6 +7,8 @@ obj-$(CONFIG_MAILBOX_TEST)      += mailbox-test.o
>
>  obj-$(CONFIG_ARM_MHU)  += arm_mhu.o
>
> +obj-$(CONFIG_IMX_MBOX) += imx-mailbox.o
> +
>  obj-$(CONFIG_PLATFORM_MHU)     += platform_mhu.o
>
>  obj-$(CONFIG_PL320_MBOX)       += pl320-ipc.o
> diff --git a/drivers/mailbox/imx-mailbox.c b/drivers/mailbox/imx-mailbox.c
> new file mode 100644
> index 000000000000..2bc9f11393b1
> --- /dev/null
> +++ b/drivers/mailbox/imx-mailbox.c
> @@ -0,0 +1,289 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2018 Pengutronix, Oleksij Rempel <o.rempel@pengutronix.de>
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/interrupt.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/mailbox_controller.h>
> +#include <linux/module.h>
> +#include <linux/of_device.h>
> +
> +/* Transmit Register */
> +#define IMX_MU_xTRn(x)         (0x00 + 4 * (x))
> +/* Receive Register */
> +#define IMX_MU_xRRn(x)         (0x10 + 4 * (x))
> +/* Status Register */
> +#define IMX_MU_xSR             0x20
> +#define IMX_MU_xSR_TEn(x)      BIT(20 + (x))
> +#define IMX_MU_xSR_RFn(x)      BIT(24 + (x))
> +#define IMX_MU_xSR_BRDIP       BIT(9)
> +
> +/* Control Register */
> +#define IMX_MU_xCR             0x24
> +/* Transmit Interrupt Enable */
> +#define IMX_MU_xCR_TIEn(x)     BIT(20 + (x))
> +/* Receive Interrupt Enable */
> +#define IMX_MU_xCR_RIEn(x)     BIT(24 + (x))
> +
> +#define IMX_MU_MAX_CHANS       4u
> +
> +struct imx_mu_priv;
> +
> +struct imx_mu_cfg {
> +       unsigned int            chans;
> +       void (*init_hw)(struct imx_mu_priv *priv);
> +};
> +
> +struct imx_mu_con_priv {
> +       int                     irq;
> +       unsigned int            bidx;
> +       unsigned int            idx;
> +};
> +
> +struct imx_mu_priv {
> +       struct device           *dev;
> +       const struct imx_mu_cfg *dcfg;
> +       void __iomem            *base;
> +
> +       struct mbox_controller  mbox;
> +       struct mbox_chan        mbox_chans[IMX_MU_MAX_CHANS];
> +
> +       struct imx_mu_con_priv  con_priv[IMX_MU_MAX_CHANS];
> +       struct clk              *clk;
> +};
> +
> +static struct imx_mu_priv *to_imx_mu_priv(struct mbox_controller *mbox)
> +{
> +       return container_of(mbox, struct imx_mu_priv, mbox);
> +}
> +
> +static void imx_mu_write(struct imx_mu_priv *priv, u32 val, u32 offs)
> +{
> +       iowrite32(val, priv->base + offs);
> +}
> +
> +static u32 imx_mu_read(struct imx_mu_priv *priv, u32 offs)
> +{
> +       return ioread32(priv->base + offs);
> +}
> +
> +static u32 imx_mu_rmw(struct imx_mu_priv *priv, u32 offs, u32 set, u32 clr)
> +{
> +       u32 val;
> +
> +       val = imx_mu_read(priv, offs);
> +       val &= ~clr;
> +       val |= set;
> +       imx_mu_write(priv, val, offs);
> +
> +       return val;
> +}
> +
> +static irqreturn_t imx_mu_isr(int irq, void *p)
> +{
> +       struct mbox_chan *chan = p;
> +       struct imx_mu_con_priv *cp = chan->con_priv;
> +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);

Please do in reversed order from long to short

> +
> +       u32 val, dat;
> +
> +       val = imx_mu_read(priv, IMX_MU_xSR);
> +       val &= IMX_MU_xSR_TEn(cp->bidx) | IMX_MU_xSR_RFn(cp->bidx);
> +       if (!val)
> +               return IRQ_NONE;
> +
> +       if (val & IMX_MU_xSR_TEn(cp->bidx)) {
> +               imx_mu_rmw(priv, IMX_MU_xCR, 0, IMX_MU_xCR_TIEn(cp->bidx));
> +               mbox_chan_txdone(chan, 0);
> +       }
> +
> +       if (val & IMX_MU_xSR_RFn(cp->bidx)) {
> +               dat = imx_mu_read(priv, IMX_MU_xRRn(cp->idx));
> +               mbox_chan_received_data(chan, (void *)&dat);
> +       }
> +
> +       return IRQ_HANDLED;
> +}
> +
> +static bool imx_mu_last_tx_done(struct mbox_chan *chan)
> +{
> +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
> +       struct imx_mu_con_priv *cp = chan->con_priv;
> +       u32 val;
> +
> +       val = imx_mu_read(priv, IMX_MU_xSR);
> +       /* test if transmit register is empty */
> +       return (!(val & IMX_MU_xSR_TEn(cp->bidx)));
> +}
> +
> +static int imx_mu_send_data(struct mbox_chan *chan, void *data)
> +{
> +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
> +       struct imx_mu_con_priv *cp = chan->con_priv;
> +       u32 *arg = data;
> +
> +       if (imx_mu_last_tx_done(chan))

return true for tx_done?
Or maybe better imx_mu_is_busy?

> +               return -EBUSY;
> +
> +       imx_mu_write(priv, *arg, IMX_MU_xTRn(cp->idx));
> +       imx_mu_rmw(priv, IMX_MU_xCR, IMX_MU_xSR_TEn(cp->bidx), 0);
> +
> +       return 0;
> +}
> +
> +static int imx_mu_startup(struct mbox_chan *chan)
> +{
> +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
> +       struct imx_mu_con_priv *cp = chan->con_priv;
> +       int ret;
> +
> +       ret = request_irq(cp->irq, imx_mu_isr,
> +                         IRQF_SHARED, "imx_mu_chan", chan);

This looks me to a bit strange as all virtual channels interrupts
line actually are the same. And we request that same irq line
repeatedly here with the same irq handler.

> +       if (ret) {
> +               dev_err(chan->mbox->dev,
> +                       "Unable to acquire IRQ %d\n", cp->irq);
> +               return ret;
> +       }
> +
> +       imx_mu_rmw(priv, IMX_MU_xCR, IMX_MU_xCR_RIEn(cp->bidx), 0);
> +
> +       return 0;
> +}
> +
> +static void imx_mu_shutdown(struct mbox_chan *chan)
> +{
> +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
> +       struct imx_mu_con_priv *cp = chan->con_priv;
> +
> +       imx_mu_rmw(priv, IMX_MU_xCR, 0,
> +                  IMX_MU_xCR_TIEn(cp->bidx) | IMX_MU_xCR_RIEn(cp->bidx));
> +
> +       free_irq(cp->irq, chan);
> +}
> +
> +static const struct mbox_chan_ops imx_mu_ops = {
> +       .send_data = imx_mu_send_data,
> +       .startup = imx_mu_startup,
> +       .shutdown = imx_mu_shutdown,
> +       .last_tx_done = imx_mu_last_tx_done,

Do we really need this?
Looking at the code, it seems .last_tx_done() is only called for polling mode.
But what you set below is:
priv->mbox.txdone_irq = true;

Or am i missed something?

> +};
> +
> +static int imx_mu_probe(struct platform_device *pdev)
> +{
> +       struct device *dev = &pdev->dev;
> +       struct resource *iomem;
> +       struct imx_mu_priv *priv;
> +       const struct imx_mu_cfg *dcfg;
> +       unsigned int i, chans;
> +       int irq, ret;
> +
> +       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> +       if (!priv)
> +               return -ENOMEM;
> +
> +       dcfg = of_device_get_match_data(dev);
> +       if (!dcfg)
> +               return -EINVAL;
> +
> +       priv->dcfg = dcfg;
> +       priv->dev = dev;
> +
> +       iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +       priv->base = devm_ioremap_resource(&pdev->dev, iomem);
> +       if (IS_ERR(priv->base))
> +               return PTR_ERR(priv->base);
> +
> +       irq = platform_get_irq(pdev, 0);
> +       if (irq <= 0)
> +               return irq < 0 ? irq : -EINVAL;

Is it possible == 0?

> +
> +       priv->clk = devm_clk_get(dev, NULL);
> +       if (IS_ERR(priv->clk)) {
> +               if (PTR_ERR(priv->clk) == -ENOENT) {
> +                       priv->clk = NULL;
> +               } else {
> +                       dev_err(dev, "Failed to get clock\n");

The line looks not be quite meaningful as it may be defer probe.

> +                       return PTR_ERR(priv->clk);
> +               }
> +       }
> +
> +       ret = clk_prepare_enable(priv->clk);
> +       if (ret) {
> +               dev_err(dev, "Failed to enable clock\n");
> +               return ret;
> +       }
> +
> +       chans = min(dcfg->chans, IMX_MU_MAX_CHANS);
> +       /* Initialize channel identifiers */
> +       for (i = 0; i < chans; i++) {
> +               struct imx_mu_con_priv *cp = &priv->con_priv[i];
> +
> +               cp->bidx = 3 - i;
> +               cp->idx = i;
> +               cp->irq = irq;
> +               priv->mbox_chans[i].con_priv = cp;
> +       }
> +
> +       priv->mbox.dev = dev;
> +       priv->mbox.ops = &imx_mu_ops;
> +       priv->mbox.chans = priv->mbox_chans;
> +       priv->mbox.num_chans = chans;
> +       priv->mbox.txdone_irq = true;
> +
> +       platform_set_drvdata(pdev, priv);
> +
> +       if (priv->dcfg->init_hw)
> +               priv->dcfg->init_hw(priv);
> +
> +       return mbox_controller_register(&priv->mbox);
> +}
> +
> +static int imx_mu_remove(struct platform_device *pdev)
> +{
> +       struct imx_mu_priv *priv = platform_get_drvdata(pdev);
> +
> +       mbox_controller_unregister(&priv->mbox);
> +       clk_disable_unprepare(priv->clk);
> +
> +       return 0;
> +}
> +
> +
> +static void imx_mu_init_imx7d_a(struct imx_mu_priv *priv)
> +{
> +       /* Set default config */
> +       imx_mu_write(priv, 0, IMX_MU_xCR);
> +}
> +
> +static const struct imx_mu_cfg imx_mu_cfg_imx7d_a = {
> +       .chans = IMX_MU_MAX_CHANS,
> +       .init_hw = imx_mu_init_imx7d_a,
> +};
> +
> +static const struct imx_mu_cfg imx_mu_cfg_imx7d_b = {
> +       .chans = IMX_MU_MAX_CHANS,
> +};
> +
> +static const struct of_device_id imx_mu_dt_ids[] = {
> +       { .compatible = "fsl,imx7s-mu-a", .data = &imx_mu_cfg_imx7d_a },
> +       { .compatible = "fsl,imx7s-mu-b", .data = &imx_mu_cfg_imx7d_b },
> +       { },
> +};
> +MODULE_DEVICE_TABLE(of, imx_mu_dt_ids);
> +
> +static struct platform_driver imx_mu_driver = {
> +       .probe          = imx_mu_probe,
> +       .remove         = imx_mu_remove,
> +       .driver = {
> +               .name   = "imx_mu",
> +               .of_match_table = imx_mu_dt_ids,
> +       },
> +};
> +module_platform_driver(imx_mu_driver);
> +
> +MODULE_AUTHOR("Oleksij Rempel <o.rempel@pengutronix.de>");
> +MODULE_DESCRIPTION("Message Unit driver for i.MX7");

s/i.MX7/i.MX

Regards
Dong Aisheng

> +MODULE_LICENSE("GPL v2");
> --
> 2.17.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-clk" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v1 4/4] mailbox: Add support for i.MX7D messaging unit
@ 2018-06-13 12:21     ` Dong Aisheng
  0 siblings, 0 replies; 54+ messages in thread
From: Dong Aisheng @ 2018-06-13 12:21 UTC (permalink / raw)
  To: Oleksij Rempel
  Cc: Shawn Guo, Fabio Estevam, Rob Herring, Mark Rutland,
	Sascha Hauer,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
	devicetree, linux-clk

Hi Oleksij,

On Fri, Jun 1, 2018 at 2:58 PM, Oleksij Rempel <o.rempel@pengutronix.de> wrote:
> The Mailbox controller is able to send messages (up to 4 32 bit words)
> between the endpoints.

Could we really be able to send up to 4 42bit words with this driver?

It looks to me the current Mailbox framework is more designed for share mem
transfer which does not fit i.MX MU well.

>
> This driver was tested using the mailbox-test driver sending messages
> between the Cortex-A7 and the Cortex-M4.

Would you please provide a guide on how to test it quickly?
I may want to give a test.

>
> Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
> ---
>  drivers/mailbox/Kconfig       |   6 +
>  drivers/mailbox/Makefile      |   2 +
>  drivers/mailbox/imx-mailbox.c | 289 ++++++++++++++++++++++++++++++++++
>  3 files changed, 297 insertions(+)
>  create mode 100644 drivers/mailbox/imx-mailbox.c
>
> diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
> index a2bb27446dce..e1d2738a2e4c 100644
> --- a/drivers/mailbox/Kconfig
> +++ b/drivers/mailbox/Kconfig
> @@ -15,6 +15,12 @@ config ARM_MHU
>           The controller has 3 mailbox channels, the last of which can be
>           used in Secure mode only.
>
> +config IMX_MBOX
> +       tristate "iMX Mailbox"
> +       depends on SOC_IMX7D || COMPILE_TEST
> +       help
> +         Mailbox implementation for iMX7D Messaging Unit (MU).
> +
>  config PLATFORM_MHU
>         tristate "Platform MHU Mailbox"
>         depends on OF
> diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
> index cc23c3a43fcd..ba2fe1b6dd62 100644
> --- a/drivers/mailbox/Makefile
> +++ b/drivers/mailbox/Makefile
> @@ -7,6 +7,8 @@ obj-$(CONFIG_MAILBOX_TEST)      += mailbox-test.o
>
>  obj-$(CONFIG_ARM_MHU)  += arm_mhu.o
>
> +obj-$(CONFIG_IMX_MBOX) += imx-mailbox.o
> +
>  obj-$(CONFIG_PLATFORM_MHU)     += platform_mhu.o
>
>  obj-$(CONFIG_PL320_MBOX)       += pl320-ipc.o
> diff --git a/drivers/mailbox/imx-mailbox.c b/drivers/mailbox/imx-mailbox.c
> new file mode 100644
> index 000000000000..2bc9f11393b1
> --- /dev/null
> +++ b/drivers/mailbox/imx-mailbox.c
> @@ -0,0 +1,289 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2018 Pengutronix, Oleksij Rempel <o.rempel@pengutronix.de>
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/interrupt.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/mailbox_controller.h>
> +#include <linux/module.h>
> +#include <linux/of_device.h>
> +
> +/* Transmit Register */
> +#define IMX_MU_xTRn(x)         (0x00 + 4 * (x))
> +/* Receive Register */
> +#define IMX_MU_xRRn(x)         (0x10 + 4 * (x))
> +/* Status Register */
> +#define IMX_MU_xSR             0x20
> +#define IMX_MU_xSR_TEn(x)      BIT(20 + (x))
> +#define IMX_MU_xSR_RFn(x)      BIT(24 + (x))
> +#define IMX_MU_xSR_BRDIP       BIT(9)
> +
> +/* Control Register */
> +#define IMX_MU_xCR             0x24
> +/* Transmit Interrupt Enable */
> +#define IMX_MU_xCR_TIEn(x)     BIT(20 + (x))
> +/* Receive Interrupt Enable */
> +#define IMX_MU_xCR_RIEn(x)     BIT(24 + (x))
> +
> +#define IMX_MU_MAX_CHANS       4u
> +
> +struct imx_mu_priv;
> +
> +struct imx_mu_cfg {
> +       unsigned int            chans;
> +       void (*init_hw)(struct imx_mu_priv *priv);
> +};
> +
> +struct imx_mu_con_priv {
> +       int                     irq;
> +       unsigned int            bidx;
> +       unsigned int            idx;
> +};
> +
> +struct imx_mu_priv {
> +       struct device           *dev;
> +       const struct imx_mu_cfg *dcfg;
> +       void __iomem            *base;
> +
> +       struct mbox_controller  mbox;
> +       struct mbox_chan        mbox_chans[IMX_MU_MAX_CHANS];
> +
> +       struct imx_mu_con_priv  con_priv[IMX_MU_MAX_CHANS];
> +       struct clk              *clk;
> +};
> +
> +static struct imx_mu_priv *to_imx_mu_priv(struct mbox_controller *mbox)
> +{
> +       return container_of(mbox, struct imx_mu_priv, mbox);
> +}
> +
> +static void imx_mu_write(struct imx_mu_priv *priv, u32 val, u32 offs)
> +{
> +       iowrite32(val, priv->base + offs);
> +}
> +
> +static u32 imx_mu_read(struct imx_mu_priv *priv, u32 offs)
> +{
> +       return ioread32(priv->base + offs);
> +}
> +
> +static u32 imx_mu_rmw(struct imx_mu_priv *priv, u32 offs, u32 set, u32 clr)
> +{
> +       u32 val;
> +
> +       val = imx_mu_read(priv, offs);
> +       val &= ~clr;
> +       val |= set;
> +       imx_mu_write(priv, val, offs);
> +
> +       return val;
> +}
> +
> +static irqreturn_t imx_mu_isr(int irq, void *p)
> +{
> +       struct mbox_chan *chan = p;
> +       struct imx_mu_con_priv *cp = chan->con_priv;
> +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);

Please do in reversed order from long to short

> +
> +       u32 val, dat;
> +
> +       val = imx_mu_read(priv, IMX_MU_xSR);
> +       val &= IMX_MU_xSR_TEn(cp->bidx) | IMX_MU_xSR_RFn(cp->bidx);
> +       if (!val)
> +               return IRQ_NONE;
> +
> +       if (val & IMX_MU_xSR_TEn(cp->bidx)) {
> +               imx_mu_rmw(priv, IMX_MU_xCR, 0, IMX_MU_xCR_TIEn(cp->bidx));
> +               mbox_chan_txdone(chan, 0);
> +       }
> +
> +       if (val & IMX_MU_xSR_RFn(cp->bidx)) {
> +               dat = imx_mu_read(priv, IMX_MU_xRRn(cp->idx));
> +               mbox_chan_received_data(chan, (void *)&dat);
> +       }
> +
> +       return IRQ_HANDLED;
> +}
> +
> +static bool imx_mu_last_tx_done(struct mbox_chan *chan)
> +{
> +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
> +       struct imx_mu_con_priv *cp = chan->con_priv;
> +       u32 val;
> +
> +       val = imx_mu_read(priv, IMX_MU_xSR);
> +       /* test if transmit register is empty */
> +       return (!(val & IMX_MU_xSR_TEn(cp->bidx)));
> +}
> +
> +static int imx_mu_send_data(struct mbox_chan *chan, void *data)
> +{
> +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
> +       struct imx_mu_con_priv *cp = chan->con_priv;
> +       u32 *arg = data;
> +
> +       if (imx_mu_last_tx_done(chan))

return true for tx_done?
Or maybe better imx_mu_is_busy?

> +               return -EBUSY;
> +
> +       imx_mu_write(priv, *arg, IMX_MU_xTRn(cp->idx));
> +       imx_mu_rmw(priv, IMX_MU_xCR, IMX_MU_xSR_TEn(cp->bidx), 0);
> +
> +       return 0;
> +}
> +
> +static int imx_mu_startup(struct mbox_chan *chan)
> +{
> +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
> +       struct imx_mu_con_priv *cp = chan->con_priv;
> +       int ret;
> +
> +       ret = request_irq(cp->irq, imx_mu_isr,
> +                         IRQF_SHARED, "imx_mu_chan", chan);

This looks me to a bit strange as all virtual channels interrupts
line actually are the same. And we request that same irq line
repeatedly here with the same irq handler.

> +       if (ret) {
> +               dev_err(chan->mbox->dev,
> +                       "Unable to acquire IRQ %d\n", cp->irq);
> +               return ret;
> +       }
> +
> +       imx_mu_rmw(priv, IMX_MU_xCR, IMX_MU_xCR_RIEn(cp->bidx), 0);
> +
> +       return 0;
> +}
> +
> +static void imx_mu_shutdown(struct mbox_chan *chan)
> +{
> +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
> +       struct imx_mu_con_priv *cp = chan->con_priv;
> +
> +       imx_mu_rmw(priv, IMX_MU_xCR, 0,
> +                  IMX_MU_xCR_TIEn(cp->bidx) | IMX_MU_xCR_RIEn(cp->bidx));
> +
> +       free_irq(cp->irq, chan);
> +}
> +
> +static const struct mbox_chan_ops imx_mu_ops = {
> +       .send_data = imx_mu_send_data,
> +       .startup = imx_mu_startup,
> +       .shutdown = imx_mu_shutdown,
> +       .last_tx_done = imx_mu_last_tx_done,

Do we really need this?
Looking at the code, it seems .last_tx_done() is only called for polling mode.
But what you set below is:
priv->mbox.txdone_irq = true;

Or am i missed something?

> +};
> +
> +static int imx_mu_probe(struct platform_device *pdev)
> +{
> +       struct device *dev = &pdev->dev;
> +       struct resource *iomem;
> +       struct imx_mu_priv *priv;
> +       const struct imx_mu_cfg *dcfg;
> +       unsigned int i, chans;
> +       int irq, ret;
> +
> +       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> +       if (!priv)
> +               return -ENOMEM;
> +
> +       dcfg = of_device_get_match_data(dev);
> +       if (!dcfg)
> +               return -EINVAL;
> +
> +       priv->dcfg = dcfg;
> +       priv->dev = dev;
> +
> +       iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +       priv->base = devm_ioremap_resource(&pdev->dev, iomem);
> +       if (IS_ERR(priv->base))
> +               return PTR_ERR(priv->base);
> +
> +       irq = platform_get_irq(pdev, 0);
> +       if (irq <= 0)
> +               return irq < 0 ? irq : -EINVAL;

Is it possible == 0?

> +
> +       priv->clk = devm_clk_get(dev, NULL);
> +       if (IS_ERR(priv->clk)) {
> +               if (PTR_ERR(priv->clk) == -ENOENT) {
> +                       priv->clk = NULL;
> +               } else {
> +                       dev_err(dev, "Failed to get clock\n");

The line looks not be quite meaningful as it may be defer probe.

> +                       return PTR_ERR(priv->clk);
> +               }
> +       }
> +
> +       ret = clk_prepare_enable(priv->clk);
> +       if (ret) {
> +               dev_err(dev, "Failed to enable clock\n");
> +               return ret;
> +       }
> +
> +       chans = min(dcfg->chans, IMX_MU_MAX_CHANS);
> +       /* Initialize channel identifiers */
> +       for (i = 0; i < chans; i++) {
> +               struct imx_mu_con_priv *cp = &priv->con_priv[i];
> +
> +               cp->bidx = 3 - i;
> +               cp->idx = i;
> +               cp->irq = irq;
> +               priv->mbox_chans[i].con_priv = cp;
> +       }
> +
> +       priv->mbox.dev = dev;
> +       priv->mbox.ops = &imx_mu_ops;
> +       priv->mbox.chans = priv->mbox_chans;
> +       priv->mbox.num_chans = chans;
> +       priv->mbox.txdone_irq = true;
> +
> +       platform_set_drvdata(pdev, priv);
> +
> +       if (priv->dcfg->init_hw)
> +               priv->dcfg->init_hw(priv);
> +
> +       return mbox_controller_register(&priv->mbox);
> +}
> +
> +static int imx_mu_remove(struct platform_device *pdev)
> +{
> +       struct imx_mu_priv *priv = platform_get_drvdata(pdev);
> +
> +       mbox_controller_unregister(&priv->mbox);
> +       clk_disable_unprepare(priv->clk);
> +
> +       return 0;
> +}
> +
> +
> +static void imx_mu_init_imx7d_a(struct imx_mu_priv *priv)
> +{
> +       /* Set default config */
> +       imx_mu_write(priv, 0, IMX_MU_xCR);
> +}
> +
> +static const struct imx_mu_cfg imx_mu_cfg_imx7d_a = {
> +       .chans = IMX_MU_MAX_CHANS,
> +       .init_hw = imx_mu_init_imx7d_a,
> +};
> +
> +static const struct imx_mu_cfg imx_mu_cfg_imx7d_b = {
> +       .chans = IMX_MU_MAX_CHANS,
> +};
> +
> +static const struct of_device_id imx_mu_dt_ids[] = {
> +       { .compatible = "fsl,imx7s-mu-a", .data = &imx_mu_cfg_imx7d_a },
> +       { .compatible = "fsl,imx7s-mu-b", .data = &imx_mu_cfg_imx7d_b },
> +       { },
> +};
> +MODULE_DEVICE_TABLE(of, imx_mu_dt_ids);
> +
> +static struct platform_driver imx_mu_driver = {
> +       .probe          = imx_mu_probe,
> +       .remove         = imx_mu_remove,
> +       .driver = {
> +               .name   = "imx_mu",
> +               .of_match_table = imx_mu_dt_ids,
> +       },
> +};
> +module_platform_driver(imx_mu_driver);
> +
> +MODULE_AUTHOR("Oleksij Rempel <o.rempel@pengutronix.de>");
> +MODULE_DESCRIPTION("Message Unit driver for i.MX7");

s/i.MX7/i.MX

Regards
Dong Aisheng

> +MODULE_LICENSE("GPL v2");
> --
> 2.17.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-clk" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 54+ messages in thread

* [PATCH v1 4/4] mailbox: Add support for i.MX7D messaging unit
@ 2018-06-13 12:21     ` Dong Aisheng
  0 siblings, 0 replies; 54+ messages in thread
From: Dong Aisheng @ 2018-06-13 12:21 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Oleksij,

On Fri, Jun 1, 2018 at 2:58 PM, Oleksij Rempel <o.rempel@pengutronix.de> wrote:
> The Mailbox controller is able to send messages (up to 4 32 bit words)
> between the endpoints.

Could we really be able to send up to 4 42bit words with this driver?

It looks to me the current Mailbox framework is more designed for share mem
transfer which does not fit i.MX MU well.

>
> This driver was tested using the mailbox-test driver sending messages
> between the Cortex-A7 and the Cortex-M4.

Would you please provide a guide on how to test it quickly?
I may want to give a test.

>
> Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
> ---
>  drivers/mailbox/Kconfig       |   6 +
>  drivers/mailbox/Makefile      |   2 +
>  drivers/mailbox/imx-mailbox.c | 289 ++++++++++++++++++++++++++++++++++
>  3 files changed, 297 insertions(+)
>  create mode 100644 drivers/mailbox/imx-mailbox.c
>
> diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
> index a2bb27446dce..e1d2738a2e4c 100644
> --- a/drivers/mailbox/Kconfig
> +++ b/drivers/mailbox/Kconfig
> @@ -15,6 +15,12 @@ config ARM_MHU
>           The controller has 3 mailbox channels, the last of which can be
>           used in Secure mode only.
>
> +config IMX_MBOX
> +       tristate "iMX Mailbox"
> +       depends on SOC_IMX7D || COMPILE_TEST
> +       help
> +         Mailbox implementation for iMX7D Messaging Unit (MU).
> +
>  config PLATFORM_MHU
>         tristate "Platform MHU Mailbox"
>         depends on OF
> diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
> index cc23c3a43fcd..ba2fe1b6dd62 100644
> --- a/drivers/mailbox/Makefile
> +++ b/drivers/mailbox/Makefile
> @@ -7,6 +7,8 @@ obj-$(CONFIG_MAILBOX_TEST)      += mailbox-test.o
>
>  obj-$(CONFIG_ARM_MHU)  += arm_mhu.o
>
> +obj-$(CONFIG_IMX_MBOX) += imx-mailbox.o
> +
>  obj-$(CONFIG_PLATFORM_MHU)     += platform_mhu.o
>
>  obj-$(CONFIG_PL320_MBOX)       += pl320-ipc.o
> diff --git a/drivers/mailbox/imx-mailbox.c b/drivers/mailbox/imx-mailbox.c
> new file mode 100644
> index 000000000000..2bc9f11393b1
> --- /dev/null
> +++ b/drivers/mailbox/imx-mailbox.c
> @@ -0,0 +1,289 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2018 Pengutronix, Oleksij Rempel <o.rempel@pengutronix.de>
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/interrupt.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/mailbox_controller.h>
> +#include <linux/module.h>
> +#include <linux/of_device.h>
> +
> +/* Transmit Register */
> +#define IMX_MU_xTRn(x)         (0x00 + 4 * (x))
> +/* Receive Register */
> +#define IMX_MU_xRRn(x)         (0x10 + 4 * (x))
> +/* Status Register */
> +#define IMX_MU_xSR             0x20
> +#define IMX_MU_xSR_TEn(x)      BIT(20 + (x))
> +#define IMX_MU_xSR_RFn(x)      BIT(24 + (x))
> +#define IMX_MU_xSR_BRDIP       BIT(9)
> +
> +/* Control Register */
> +#define IMX_MU_xCR             0x24
> +/* Transmit Interrupt Enable */
> +#define IMX_MU_xCR_TIEn(x)     BIT(20 + (x))
> +/* Receive Interrupt Enable */
> +#define IMX_MU_xCR_RIEn(x)     BIT(24 + (x))
> +
> +#define IMX_MU_MAX_CHANS       4u
> +
> +struct imx_mu_priv;
> +
> +struct imx_mu_cfg {
> +       unsigned int            chans;
> +       void (*init_hw)(struct imx_mu_priv *priv);
> +};
> +
> +struct imx_mu_con_priv {
> +       int                     irq;
> +       unsigned int            bidx;
> +       unsigned int            idx;
> +};
> +
> +struct imx_mu_priv {
> +       struct device           *dev;
> +       const struct imx_mu_cfg *dcfg;
> +       void __iomem            *base;
> +
> +       struct mbox_controller  mbox;
> +       struct mbox_chan        mbox_chans[IMX_MU_MAX_CHANS];
> +
> +       struct imx_mu_con_priv  con_priv[IMX_MU_MAX_CHANS];
> +       struct clk              *clk;
> +};
> +
> +static struct imx_mu_priv *to_imx_mu_priv(struct mbox_controller *mbox)
> +{
> +       return container_of(mbox, struct imx_mu_priv, mbox);
> +}
> +
> +static void imx_mu_write(struct imx_mu_priv *priv, u32 val, u32 offs)
> +{
> +       iowrite32(val, priv->base + offs);
> +}
> +
> +static u32 imx_mu_read(struct imx_mu_priv *priv, u32 offs)
> +{
> +       return ioread32(priv->base + offs);
> +}
> +
> +static u32 imx_mu_rmw(struct imx_mu_priv *priv, u32 offs, u32 set, u32 clr)
> +{
> +       u32 val;
> +
> +       val = imx_mu_read(priv, offs);
> +       val &= ~clr;
> +       val |= set;
> +       imx_mu_write(priv, val, offs);
> +
> +       return val;
> +}
> +
> +static irqreturn_t imx_mu_isr(int irq, void *p)
> +{
> +       struct mbox_chan *chan = p;
> +       struct imx_mu_con_priv *cp = chan->con_priv;
> +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);

Please do in reversed order from long to short

> +
> +       u32 val, dat;
> +
> +       val = imx_mu_read(priv, IMX_MU_xSR);
> +       val &= IMX_MU_xSR_TEn(cp->bidx) | IMX_MU_xSR_RFn(cp->bidx);
> +       if (!val)
> +               return IRQ_NONE;
> +
> +       if (val & IMX_MU_xSR_TEn(cp->bidx)) {
> +               imx_mu_rmw(priv, IMX_MU_xCR, 0, IMX_MU_xCR_TIEn(cp->bidx));
> +               mbox_chan_txdone(chan, 0);
> +       }
> +
> +       if (val & IMX_MU_xSR_RFn(cp->bidx)) {
> +               dat = imx_mu_read(priv, IMX_MU_xRRn(cp->idx));
> +               mbox_chan_received_data(chan, (void *)&dat);
> +       }
> +
> +       return IRQ_HANDLED;
> +}
> +
> +static bool imx_mu_last_tx_done(struct mbox_chan *chan)
> +{
> +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
> +       struct imx_mu_con_priv *cp = chan->con_priv;
> +       u32 val;
> +
> +       val = imx_mu_read(priv, IMX_MU_xSR);
> +       /* test if transmit register is empty */
> +       return (!(val & IMX_MU_xSR_TEn(cp->bidx)));
> +}
> +
> +static int imx_mu_send_data(struct mbox_chan *chan, void *data)
> +{
> +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
> +       struct imx_mu_con_priv *cp = chan->con_priv;
> +       u32 *arg = data;
> +
> +       if (imx_mu_last_tx_done(chan))

return true for tx_done?
Or maybe better imx_mu_is_busy?

> +               return -EBUSY;
> +
> +       imx_mu_write(priv, *arg, IMX_MU_xTRn(cp->idx));
> +       imx_mu_rmw(priv, IMX_MU_xCR, IMX_MU_xSR_TEn(cp->bidx), 0);
> +
> +       return 0;
> +}
> +
> +static int imx_mu_startup(struct mbox_chan *chan)
> +{
> +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
> +       struct imx_mu_con_priv *cp = chan->con_priv;
> +       int ret;
> +
> +       ret = request_irq(cp->irq, imx_mu_isr,
> +                         IRQF_SHARED, "imx_mu_chan", chan);

This looks me to a bit strange as all virtual channels interrupts
line actually are the same. And we request that same irq line
repeatedly here with the same irq handler.

> +       if (ret) {
> +               dev_err(chan->mbox->dev,
> +                       "Unable to acquire IRQ %d\n", cp->irq);
> +               return ret;
> +       }
> +
> +       imx_mu_rmw(priv, IMX_MU_xCR, IMX_MU_xCR_RIEn(cp->bidx), 0);
> +
> +       return 0;
> +}
> +
> +static void imx_mu_shutdown(struct mbox_chan *chan)
> +{
> +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
> +       struct imx_mu_con_priv *cp = chan->con_priv;
> +
> +       imx_mu_rmw(priv, IMX_MU_xCR, 0,
> +                  IMX_MU_xCR_TIEn(cp->bidx) | IMX_MU_xCR_RIEn(cp->bidx));
> +
> +       free_irq(cp->irq, chan);
> +}
> +
> +static const struct mbox_chan_ops imx_mu_ops = {
> +       .send_data = imx_mu_send_data,
> +       .startup = imx_mu_startup,
> +       .shutdown = imx_mu_shutdown,
> +       .last_tx_done = imx_mu_last_tx_done,

Do we really need this?
Looking at the code, it seems .last_tx_done() is only called for polling mode.
But what you set below is:
priv->mbox.txdone_irq = true;

Or am i missed something?

> +};
> +
> +static int imx_mu_probe(struct platform_device *pdev)
> +{
> +       struct device *dev = &pdev->dev;
> +       struct resource *iomem;
> +       struct imx_mu_priv *priv;
> +       const struct imx_mu_cfg *dcfg;
> +       unsigned int i, chans;
> +       int irq, ret;
> +
> +       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> +       if (!priv)
> +               return -ENOMEM;
> +
> +       dcfg = of_device_get_match_data(dev);
> +       if (!dcfg)
> +               return -EINVAL;
> +
> +       priv->dcfg = dcfg;
> +       priv->dev = dev;
> +
> +       iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +       priv->base = devm_ioremap_resource(&pdev->dev, iomem);
> +       if (IS_ERR(priv->base))
> +               return PTR_ERR(priv->base);
> +
> +       irq = platform_get_irq(pdev, 0);
> +       if (irq <= 0)
> +               return irq < 0 ? irq : -EINVAL;

Is it possible == 0?

> +
> +       priv->clk = devm_clk_get(dev, NULL);
> +       if (IS_ERR(priv->clk)) {
> +               if (PTR_ERR(priv->clk) == -ENOENT) {
> +                       priv->clk = NULL;
> +               } else {
> +                       dev_err(dev, "Failed to get clock\n");

The line looks not be quite meaningful as it may be defer probe.

> +                       return PTR_ERR(priv->clk);
> +               }
> +       }
> +
> +       ret = clk_prepare_enable(priv->clk);
> +       if (ret) {
> +               dev_err(dev, "Failed to enable clock\n");
> +               return ret;
> +       }
> +
> +       chans = min(dcfg->chans, IMX_MU_MAX_CHANS);
> +       /* Initialize channel identifiers */
> +       for (i = 0; i < chans; i++) {
> +               struct imx_mu_con_priv *cp = &priv->con_priv[i];
> +
> +               cp->bidx = 3 - i;
> +               cp->idx = i;
> +               cp->irq = irq;
> +               priv->mbox_chans[i].con_priv = cp;
> +       }
> +
> +       priv->mbox.dev = dev;
> +       priv->mbox.ops = &imx_mu_ops;
> +       priv->mbox.chans = priv->mbox_chans;
> +       priv->mbox.num_chans = chans;
> +       priv->mbox.txdone_irq = true;
> +
> +       platform_set_drvdata(pdev, priv);
> +
> +       if (priv->dcfg->init_hw)
> +               priv->dcfg->init_hw(priv);
> +
> +       return mbox_controller_register(&priv->mbox);
> +}
> +
> +static int imx_mu_remove(struct platform_device *pdev)
> +{
> +       struct imx_mu_priv *priv = platform_get_drvdata(pdev);
> +
> +       mbox_controller_unregister(&priv->mbox);
> +       clk_disable_unprepare(priv->clk);
> +
> +       return 0;
> +}
> +
> +
> +static void imx_mu_init_imx7d_a(struct imx_mu_priv *priv)
> +{
> +       /* Set default config */
> +       imx_mu_write(priv, 0, IMX_MU_xCR);
> +}
> +
> +static const struct imx_mu_cfg imx_mu_cfg_imx7d_a = {
> +       .chans = IMX_MU_MAX_CHANS,
> +       .init_hw = imx_mu_init_imx7d_a,
> +};
> +
> +static const struct imx_mu_cfg imx_mu_cfg_imx7d_b = {
> +       .chans = IMX_MU_MAX_CHANS,
> +};
> +
> +static const struct of_device_id imx_mu_dt_ids[] = {
> +       { .compatible = "fsl,imx7s-mu-a", .data = &imx_mu_cfg_imx7d_a },
> +       { .compatible = "fsl,imx7s-mu-b", .data = &imx_mu_cfg_imx7d_b },
> +       { },
> +};
> +MODULE_DEVICE_TABLE(of, imx_mu_dt_ids);
> +
> +static struct platform_driver imx_mu_driver = {
> +       .probe          = imx_mu_probe,
> +       .remove         = imx_mu_remove,
> +       .driver = {
> +               .name   = "imx_mu",
> +               .of_match_table = imx_mu_dt_ids,
> +       },
> +};
> +module_platform_driver(imx_mu_driver);
> +
> +MODULE_AUTHOR("Oleksij Rempel <o.rempel@pengutronix.de>");
> +MODULE_DESCRIPTION("Message Unit driver for i.MX7");

s/i.MX7/i.MX

Regards
Dong Aisheng

> +MODULE_LICENSE("GPL v2");
> --
> 2.17.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-clk" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v1 4/4] mailbox: Add support for i.MX7D messaging unit
  2018-06-13 12:21     ` Dong Aisheng
  (?)
@ 2018-06-13 12:24       ` Dong Aisheng
  -1 siblings, 0 replies; 54+ messages in thread
From: Dong Aisheng @ 2018-06-13 12:24 UTC (permalink / raw)
  To: Oleksij Rempel
  Cc: Mark Rutland, devicetree, Peng Fan, Richard Zhu, Rob Herring,
	dl-linux-imx, Sascha Hauer, Dong Aisheng, Fabio Estevam,
	Shawn Guo, linux-clk,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE

Copy linux-imx@nxp.com and more related guys to comment

On Wed, Jun 13, 2018 at 8:21 PM, Dong Aisheng <dongas86@gmail.com> wrote:
> Hi Oleksij,
>
> On Fri, Jun 1, 2018 at 2:58 PM, Oleksij Rempel <o.rempel@pengutronix.de> wrote:
>> The Mailbox controller is able to send messages (up to 4 32 bit words)
>> between the endpoints.
>
> Could we really be able to send up to 4 42bit words with this driver?
>
> It looks to me the current Mailbox framework is more designed for share mem
> transfer which does not fit i.MX MU well.
>
>>
>> This driver was tested using the mailbox-test driver sending messages
>> between the Cortex-A7 and the Cortex-M4.
>
> Would you please provide a guide on how to test it quickly?
> I may want to give a test.
>
>>
>> Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
>> ---
>>  drivers/mailbox/Kconfig       |   6 +
>>  drivers/mailbox/Makefile      |   2 +
>>  drivers/mailbox/imx-mailbox.c | 289 ++++++++++++++++++++++++++++++++++
>>  3 files changed, 297 insertions(+)
>>  create mode 100644 drivers/mailbox/imx-mailbox.c
>>
>> diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
>> index a2bb27446dce..e1d2738a2e4c 100644
>> --- a/drivers/mailbox/Kconfig
>> +++ b/drivers/mailbox/Kconfig
>> @@ -15,6 +15,12 @@ config ARM_MHU
>>           The controller has 3 mailbox channels, the last of which can be
>>           used in Secure mode only.
>>
>> +config IMX_MBOX
>> +       tristate "iMX Mailbox"
>> +       depends on SOC_IMX7D || COMPILE_TEST
>> +       help
>> +         Mailbox implementation for iMX7D Messaging Unit (MU).
>> +
>>  config PLATFORM_MHU
>>         tristate "Platform MHU Mailbox"
>>         depends on OF
>> diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
>> index cc23c3a43fcd..ba2fe1b6dd62 100644
>> --- a/drivers/mailbox/Makefile
>> +++ b/drivers/mailbox/Makefile
>> @@ -7,6 +7,8 @@ obj-$(CONFIG_MAILBOX_TEST)      += mailbox-test.o
>>
>>  obj-$(CONFIG_ARM_MHU)  += arm_mhu.o
>>
>> +obj-$(CONFIG_IMX_MBOX) += imx-mailbox.o
>> +
>>  obj-$(CONFIG_PLATFORM_MHU)     += platform_mhu.o
>>
>>  obj-$(CONFIG_PL320_MBOX)       += pl320-ipc.o
>> diff --git a/drivers/mailbox/imx-mailbox.c b/drivers/mailbox/imx-mailbox.c
>> new file mode 100644
>> index 000000000000..2bc9f11393b1
>> --- /dev/null
>> +++ b/drivers/mailbox/imx-mailbox.c
>> @@ -0,0 +1,289 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Copyright (c) 2018 Pengutronix, Oleksij Rempel <o.rempel@pengutronix.de>
>> + */
>> +
>> +#include <linux/clk.h>
>> +#include <linux/interrupt.h>
>> +#include <linux/io.h>
>> +#include <linux/kernel.h>
>> +#include <linux/mailbox_controller.h>
>> +#include <linux/module.h>
>> +#include <linux/of_device.h>
>> +
>> +/* Transmit Register */
>> +#define IMX_MU_xTRn(x)         (0x00 + 4 * (x))
>> +/* Receive Register */
>> +#define IMX_MU_xRRn(x)         (0x10 + 4 * (x))
>> +/* Status Register */
>> +#define IMX_MU_xSR             0x20
>> +#define IMX_MU_xSR_TEn(x)      BIT(20 + (x))
>> +#define IMX_MU_xSR_RFn(x)      BIT(24 + (x))
>> +#define IMX_MU_xSR_BRDIP       BIT(9)
>> +
>> +/* Control Register */
>> +#define IMX_MU_xCR             0x24
>> +/* Transmit Interrupt Enable */
>> +#define IMX_MU_xCR_TIEn(x)     BIT(20 + (x))
>> +/* Receive Interrupt Enable */
>> +#define IMX_MU_xCR_RIEn(x)     BIT(24 + (x))
>> +
>> +#define IMX_MU_MAX_CHANS       4u
>> +
>> +struct imx_mu_priv;
>> +
>> +struct imx_mu_cfg {
>> +       unsigned int            chans;
>> +       void (*init_hw)(struct imx_mu_priv *priv);
>> +};
>> +
>> +struct imx_mu_con_priv {
>> +       int                     irq;
>> +       unsigned int            bidx;
>> +       unsigned int            idx;
>> +};
>> +
>> +struct imx_mu_priv {
>> +       struct device           *dev;
>> +       const struct imx_mu_cfg *dcfg;
>> +       void __iomem            *base;
>> +
>> +       struct mbox_controller  mbox;
>> +       struct mbox_chan        mbox_chans[IMX_MU_MAX_CHANS];
>> +
>> +       struct imx_mu_con_priv  con_priv[IMX_MU_MAX_CHANS];
>> +       struct clk              *clk;
>> +};
>> +
>> +static struct imx_mu_priv *to_imx_mu_priv(struct mbox_controller *mbox)
>> +{
>> +       return container_of(mbox, struct imx_mu_priv, mbox);
>> +}
>> +
>> +static void imx_mu_write(struct imx_mu_priv *priv, u32 val, u32 offs)
>> +{
>> +       iowrite32(val, priv->base + offs);
>> +}
>> +
>> +static u32 imx_mu_read(struct imx_mu_priv *priv, u32 offs)
>> +{
>> +       return ioread32(priv->base + offs);
>> +}
>> +
>> +static u32 imx_mu_rmw(struct imx_mu_priv *priv, u32 offs, u32 set, u32 clr)
>> +{
>> +       u32 val;
>> +
>> +       val = imx_mu_read(priv, offs);
>> +       val &= ~clr;
>> +       val |= set;
>> +       imx_mu_write(priv, val, offs);
>> +
>> +       return val;
>> +}
>> +
>> +static irqreturn_t imx_mu_isr(int irq, void *p)
>> +{
>> +       struct mbox_chan *chan = p;
>> +       struct imx_mu_con_priv *cp = chan->con_priv;
>> +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
>
> Please do in reversed order from long to short
>
>> +
>> +       u32 val, dat;
>> +
>> +       val = imx_mu_read(priv, IMX_MU_xSR);
>> +       val &= IMX_MU_xSR_TEn(cp->bidx) | IMX_MU_xSR_RFn(cp->bidx);
>> +       if (!val)
>> +               return IRQ_NONE;
>> +
>> +       if (val & IMX_MU_xSR_TEn(cp->bidx)) {
>> +               imx_mu_rmw(priv, IMX_MU_xCR, 0, IMX_MU_xCR_TIEn(cp->bidx));
>> +               mbox_chan_txdone(chan, 0);
>> +       }
>> +
>> +       if (val & IMX_MU_xSR_RFn(cp->bidx)) {
>> +               dat = imx_mu_read(priv, IMX_MU_xRRn(cp->idx));
>> +               mbox_chan_received_data(chan, (void *)&dat);
>> +       }
>> +
>> +       return IRQ_HANDLED;
>> +}
>> +
>> +static bool imx_mu_last_tx_done(struct mbox_chan *chan)
>> +{
>> +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
>> +       struct imx_mu_con_priv *cp = chan->con_priv;
>> +       u32 val;
>> +
>> +       val = imx_mu_read(priv, IMX_MU_xSR);
>> +       /* test if transmit register is empty */
>> +       return (!(val & IMX_MU_xSR_TEn(cp->bidx)));
>> +}
>> +
>> +static int imx_mu_send_data(struct mbox_chan *chan, void *data)
>> +{
>> +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
>> +       struct imx_mu_con_priv *cp = chan->con_priv;
>> +       u32 *arg = data;
>> +
>> +       if (imx_mu_last_tx_done(chan))
>
> return true for tx_done?
> Or maybe better imx_mu_is_busy?
>
>> +               return -EBUSY;
>> +
>> +       imx_mu_write(priv, *arg, IMX_MU_xTRn(cp->idx));
>> +       imx_mu_rmw(priv, IMX_MU_xCR, IMX_MU_xSR_TEn(cp->bidx), 0);
>> +
>> +       return 0;
>> +}
>> +
>> +static int imx_mu_startup(struct mbox_chan *chan)
>> +{
>> +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
>> +       struct imx_mu_con_priv *cp = chan->con_priv;
>> +       int ret;
>> +
>> +       ret = request_irq(cp->irq, imx_mu_isr,
>> +                         IRQF_SHARED, "imx_mu_chan", chan);
>
> This looks me to a bit strange as all virtual channels interrupts
> line actually are the same. And we request that same irq line
> repeatedly here with the same irq handler.
>
>> +       if (ret) {
>> +               dev_err(chan->mbox->dev,
>> +                       "Unable to acquire IRQ %d\n", cp->irq);
>> +               return ret;
>> +       }
>> +
>> +       imx_mu_rmw(priv, IMX_MU_xCR, IMX_MU_xCR_RIEn(cp->bidx), 0);
>> +
>> +       return 0;
>> +}
>> +
>> +static void imx_mu_shutdown(struct mbox_chan *chan)
>> +{
>> +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
>> +       struct imx_mu_con_priv *cp = chan->con_priv;
>> +
>> +       imx_mu_rmw(priv, IMX_MU_xCR, 0,
>> +                  IMX_MU_xCR_TIEn(cp->bidx) | IMX_MU_xCR_RIEn(cp->bidx));
>> +
>> +       free_irq(cp->irq, chan);
>> +}
>> +
>> +static const struct mbox_chan_ops imx_mu_ops = {
>> +       .send_data = imx_mu_send_data,
>> +       .startup = imx_mu_startup,
>> +       .shutdown = imx_mu_shutdown,
>> +       .last_tx_done = imx_mu_last_tx_done,
>
> Do we really need this?
> Looking at the code, it seems .last_tx_done() is only called for polling mode.
> But what you set below is:
> priv->mbox.txdone_irq = true;
>
> Or am i missed something?
>
>> +};
>> +
>> +static int imx_mu_probe(struct platform_device *pdev)
>> +{
>> +       struct device *dev = &pdev->dev;
>> +       struct resource *iomem;
>> +       struct imx_mu_priv *priv;
>> +       const struct imx_mu_cfg *dcfg;
>> +       unsigned int i, chans;
>> +       int irq, ret;
>> +
>> +       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
>> +       if (!priv)
>> +               return -ENOMEM;
>> +
>> +       dcfg = of_device_get_match_data(dev);
>> +       if (!dcfg)
>> +               return -EINVAL;
>> +
>> +       priv->dcfg = dcfg;
>> +       priv->dev = dev;
>> +
>> +       iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> +       priv->base = devm_ioremap_resource(&pdev->dev, iomem);
>> +       if (IS_ERR(priv->base))
>> +               return PTR_ERR(priv->base);
>> +
>> +       irq = platform_get_irq(pdev, 0);
>> +       if (irq <= 0)
>> +               return irq < 0 ? irq : -EINVAL;
>
> Is it possible == 0?
>
>> +
>> +       priv->clk = devm_clk_get(dev, NULL);
>> +       if (IS_ERR(priv->clk)) {
>> +               if (PTR_ERR(priv->clk) == -ENOENT) {
>> +                       priv->clk = NULL;
>> +               } else {
>> +                       dev_err(dev, "Failed to get clock\n");
>
> The line looks not be quite meaningful as it may be defer probe.
>
>> +                       return PTR_ERR(priv->clk);
>> +               }
>> +       }
>> +
>> +       ret = clk_prepare_enable(priv->clk);
>> +       if (ret) {
>> +               dev_err(dev, "Failed to enable clock\n");
>> +               return ret;
>> +       }
>> +
>> +       chans = min(dcfg->chans, IMX_MU_MAX_CHANS);
>> +       /* Initialize channel identifiers */
>> +       for (i = 0; i < chans; i++) {
>> +               struct imx_mu_con_priv *cp = &priv->con_priv[i];
>> +
>> +               cp->bidx = 3 - i;
>> +               cp->idx = i;
>> +               cp->irq = irq;
>> +               priv->mbox_chans[i].con_priv = cp;
>> +       }
>> +
>> +       priv->mbox.dev = dev;
>> +       priv->mbox.ops = &imx_mu_ops;
>> +       priv->mbox.chans = priv->mbox_chans;
>> +       priv->mbox.num_chans = chans;
>> +       priv->mbox.txdone_irq = true;
>> +
>> +       platform_set_drvdata(pdev, priv);
>> +
>> +       if (priv->dcfg->init_hw)
>> +               priv->dcfg->init_hw(priv);
>> +
>> +       return mbox_controller_register(&priv->mbox);
>> +}
>> +
>> +static int imx_mu_remove(struct platform_device *pdev)
>> +{
>> +       struct imx_mu_priv *priv = platform_get_drvdata(pdev);
>> +
>> +       mbox_controller_unregister(&priv->mbox);
>> +       clk_disable_unprepare(priv->clk);
>> +
>> +       return 0;
>> +}
>> +
>> +
>> +static void imx_mu_init_imx7d_a(struct imx_mu_priv *priv)
>> +{
>> +       /* Set default config */
>> +       imx_mu_write(priv, 0, IMX_MU_xCR);
>> +}
>> +
>> +static const struct imx_mu_cfg imx_mu_cfg_imx7d_a = {
>> +       .chans = IMX_MU_MAX_CHANS,
>> +       .init_hw = imx_mu_init_imx7d_a,
>> +};
>> +
>> +static const struct imx_mu_cfg imx_mu_cfg_imx7d_b = {
>> +       .chans = IMX_MU_MAX_CHANS,
>> +};
>> +
>> +static const struct of_device_id imx_mu_dt_ids[] = {
>> +       { .compatible = "fsl,imx7s-mu-a", .data = &imx_mu_cfg_imx7d_a },
>> +       { .compatible = "fsl,imx7s-mu-b", .data = &imx_mu_cfg_imx7d_b },
>> +       { },
>> +};
>> +MODULE_DEVICE_TABLE(of, imx_mu_dt_ids);
>> +
>> +static struct platform_driver imx_mu_driver = {
>> +       .probe          = imx_mu_probe,
>> +       .remove         = imx_mu_remove,
>> +       .driver = {
>> +               .name   = "imx_mu",
>> +               .of_match_table = imx_mu_dt_ids,
>> +       },
>> +};
>> +module_platform_driver(imx_mu_driver);
>> +
>> +MODULE_AUTHOR("Oleksij Rempel <o.rempel@pengutronix.de>");
>> +MODULE_DESCRIPTION("Message Unit driver for i.MX7");
>
> s/i.MX7/i.MX
>
> Regards
> Dong Aisheng
>
>> +MODULE_LICENSE("GPL v2");
>> --
>> 2.17.1
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-clk" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v1 4/4] mailbox: Add support for i.MX7D messaging unit
@ 2018-06-13 12:24       ` Dong Aisheng
  0 siblings, 0 replies; 54+ messages in thread
From: Dong Aisheng @ 2018-06-13 12:24 UTC (permalink / raw)
  To: Oleksij Rempel
  Cc: Shawn Guo, Fabio Estevam, Rob Herring, Mark Rutland,
	Sascha Hauer,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
	devicetree, linux-clk, dl-linux-imx, Dong Aisheng, Peng Fan,
	Richard Zhu

Copy linux-imx@nxp.com and more related guys to comment

On Wed, Jun 13, 2018 at 8:21 PM, Dong Aisheng <dongas86@gmail.com> wrote:
> Hi Oleksij,
>
> On Fri, Jun 1, 2018 at 2:58 PM, Oleksij Rempel <o.rempel@pengutronix.de> wrote:
>> The Mailbox controller is able to send messages (up to 4 32 bit words)
>> between the endpoints.
>
> Could we really be able to send up to 4 42bit words with this driver?
>
> It looks to me the current Mailbox framework is more designed for share mem
> transfer which does not fit i.MX MU well.
>
>>
>> This driver was tested using the mailbox-test driver sending messages
>> between the Cortex-A7 and the Cortex-M4.
>
> Would you please provide a guide on how to test it quickly?
> I may want to give a test.
>
>>
>> Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
>> ---
>>  drivers/mailbox/Kconfig       |   6 +
>>  drivers/mailbox/Makefile      |   2 +
>>  drivers/mailbox/imx-mailbox.c | 289 ++++++++++++++++++++++++++++++++++
>>  3 files changed, 297 insertions(+)
>>  create mode 100644 drivers/mailbox/imx-mailbox.c
>>
>> diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
>> index a2bb27446dce..e1d2738a2e4c 100644
>> --- a/drivers/mailbox/Kconfig
>> +++ b/drivers/mailbox/Kconfig
>> @@ -15,6 +15,12 @@ config ARM_MHU
>>           The controller has 3 mailbox channels, the last of which can be
>>           used in Secure mode only.
>>
>> +config IMX_MBOX
>> +       tristate "iMX Mailbox"
>> +       depends on SOC_IMX7D || COMPILE_TEST
>> +       help
>> +         Mailbox implementation for iMX7D Messaging Unit (MU).
>> +
>>  config PLATFORM_MHU
>>         tristate "Platform MHU Mailbox"
>>         depends on OF
>> diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
>> index cc23c3a43fcd..ba2fe1b6dd62 100644
>> --- a/drivers/mailbox/Makefile
>> +++ b/drivers/mailbox/Makefile
>> @@ -7,6 +7,8 @@ obj-$(CONFIG_MAILBOX_TEST)      += mailbox-test.o
>>
>>  obj-$(CONFIG_ARM_MHU)  += arm_mhu.o
>>
>> +obj-$(CONFIG_IMX_MBOX) += imx-mailbox.o
>> +
>>  obj-$(CONFIG_PLATFORM_MHU)     += platform_mhu.o
>>
>>  obj-$(CONFIG_PL320_MBOX)       += pl320-ipc.o
>> diff --git a/drivers/mailbox/imx-mailbox.c b/drivers/mailbox/imx-mailbox.c
>> new file mode 100644
>> index 000000000000..2bc9f11393b1
>> --- /dev/null
>> +++ b/drivers/mailbox/imx-mailbox.c
>> @@ -0,0 +1,289 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Copyright (c) 2018 Pengutronix, Oleksij Rempel <o.rempel@pengutronix.de>
>> + */
>> +
>> +#include <linux/clk.h>
>> +#include <linux/interrupt.h>
>> +#include <linux/io.h>
>> +#include <linux/kernel.h>
>> +#include <linux/mailbox_controller.h>
>> +#include <linux/module.h>
>> +#include <linux/of_device.h>
>> +
>> +/* Transmit Register */
>> +#define IMX_MU_xTRn(x)         (0x00 + 4 * (x))
>> +/* Receive Register */
>> +#define IMX_MU_xRRn(x)         (0x10 + 4 * (x))
>> +/* Status Register */
>> +#define IMX_MU_xSR             0x20
>> +#define IMX_MU_xSR_TEn(x)      BIT(20 + (x))
>> +#define IMX_MU_xSR_RFn(x)      BIT(24 + (x))
>> +#define IMX_MU_xSR_BRDIP       BIT(9)
>> +
>> +/* Control Register */
>> +#define IMX_MU_xCR             0x24
>> +/* Transmit Interrupt Enable */
>> +#define IMX_MU_xCR_TIEn(x)     BIT(20 + (x))
>> +/* Receive Interrupt Enable */
>> +#define IMX_MU_xCR_RIEn(x)     BIT(24 + (x))
>> +
>> +#define IMX_MU_MAX_CHANS       4u
>> +
>> +struct imx_mu_priv;
>> +
>> +struct imx_mu_cfg {
>> +       unsigned int            chans;
>> +       void (*init_hw)(struct imx_mu_priv *priv);
>> +};
>> +
>> +struct imx_mu_con_priv {
>> +       int                     irq;
>> +       unsigned int            bidx;
>> +       unsigned int            idx;
>> +};
>> +
>> +struct imx_mu_priv {
>> +       struct device           *dev;
>> +       const struct imx_mu_cfg *dcfg;
>> +       void __iomem            *base;
>> +
>> +       struct mbox_controller  mbox;
>> +       struct mbox_chan        mbox_chans[IMX_MU_MAX_CHANS];
>> +
>> +       struct imx_mu_con_priv  con_priv[IMX_MU_MAX_CHANS];
>> +       struct clk              *clk;
>> +};
>> +
>> +static struct imx_mu_priv *to_imx_mu_priv(struct mbox_controller *mbox)
>> +{
>> +       return container_of(mbox, struct imx_mu_priv, mbox);
>> +}
>> +
>> +static void imx_mu_write(struct imx_mu_priv *priv, u32 val, u32 offs)
>> +{
>> +       iowrite32(val, priv->base + offs);
>> +}
>> +
>> +static u32 imx_mu_read(struct imx_mu_priv *priv, u32 offs)
>> +{
>> +       return ioread32(priv->base + offs);
>> +}
>> +
>> +static u32 imx_mu_rmw(struct imx_mu_priv *priv, u32 offs, u32 set, u32 clr)
>> +{
>> +       u32 val;
>> +
>> +       val = imx_mu_read(priv, offs);
>> +       val &= ~clr;
>> +       val |= set;
>> +       imx_mu_write(priv, val, offs);
>> +
>> +       return val;
>> +}
>> +
>> +static irqreturn_t imx_mu_isr(int irq, void *p)
>> +{
>> +       struct mbox_chan *chan = p;
>> +       struct imx_mu_con_priv *cp = chan->con_priv;
>> +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
>
> Please do in reversed order from long to short
>
>> +
>> +       u32 val, dat;
>> +
>> +       val = imx_mu_read(priv, IMX_MU_xSR);
>> +       val &= IMX_MU_xSR_TEn(cp->bidx) | IMX_MU_xSR_RFn(cp->bidx);
>> +       if (!val)
>> +               return IRQ_NONE;
>> +
>> +       if (val & IMX_MU_xSR_TEn(cp->bidx)) {
>> +               imx_mu_rmw(priv, IMX_MU_xCR, 0, IMX_MU_xCR_TIEn(cp->bidx));
>> +               mbox_chan_txdone(chan, 0);
>> +       }
>> +
>> +       if (val & IMX_MU_xSR_RFn(cp->bidx)) {
>> +               dat = imx_mu_read(priv, IMX_MU_xRRn(cp->idx));
>> +               mbox_chan_received_data(chan, (void *)&dat);
>> +       }
>> +
>> +       return IRQ_HANDLED;
>> +}
>> +
>> +static bool imx_mu_last_tx_done(struct mbox_chan *chan)
>> +{
>> +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
>> +       struct imx_mu_con_priv *cp = chan->con_priv;
>> +       u32 val;
>> +
>> +       val = imx_mu_read(priv, IMX_MU_xSR);
>> +       /* test if transmit register is empty */
>> +       return (!(val & IMX_MU_xSR_TEn(cp->bidx)));
>> +}
>> +
>> +static int imx_mu_send_data(struct mbox_chan *chan, void *data)
>> +{
>> +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
>> +       struct imx_mu_con_priv *cp = chan->con_priv;
>> +       u32 *arg = data;
>> +
>> +       if (imx_mu_last_tx_done(chan))
>
> return true for tx_done?
> Or maybe better imx_mu_is_busy?
>
>> +               return -EBUSY;
>> +
>> +       imx_mu_write(priv, *arg, IMX_MU_xTRn(cp->idx));
>> +       imx_mu_rmw(priv, IMX_MU_xCR, IMX_MU_xSR_TEn(cp->bidx), 0);
>> +
>> +       return 0;
>> +}
>> +
>> +static int imx_mu_startup(struct mbox_chan *chan)
>> +{
>> +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
>> +       struct imx_mu_con_priv *cp = chan->con_priv;
>> +       int ret;
>> +
>> +       ret = request_irq(cp->irq, imx_mu_isr,
>> +                         IRQF_SHARED, "imx_mu_chan", chan);
>
> This looks me to a bit strange as all virtual channels interrupts
> line actually are the same. And we request that same irq line
> repeatedly here with the same irq handler.
>
>> +       if (ret) {
>> +               dev_err(chan->mbox->dev,
>> +                       "Unable to acquire IRQ %d\n", cp->irq);
>> +               return ret;
>> +       }
>> +
>> +       imx_mu_rmw(priv, IMX_MU_xCR, IMX_MU_xCR_RIEn(cp->bidx), 0);
>> +
>> +       return 0;
>> +}
>> +
>> +static void imx_mu_shutdown(struct mbox_chan *chan)
>> +{
>> +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
>> +       struct imx_mu_con_priv *cp = chan->con_priv;
>> +
>> +       imx_mu_rmw(priv, IMX_MU_xCR, 0,
>> +                  IMX_MU_xCR_TIEn(cp->bidx) | IMX_MU_xCR_RIEn(cp->bidx));
>> +
>> +       free_irq(cp->irq, chan);
>> +}
>> +
>> +static const struct mbox_chan_ops imx_mu_ops = {
>> +       .send_data = imx_mu_send_data,
>> +       .startup = imx_mu_startup,
>> +       .shutdown = imx_mu_shutdown,
>> +       .last_tx_done = imx_mu_last_tx_done,
>
> Do we really need this?
> Looking at the code, it seems .last_tx_done() is only called for polling mode.
> But what you set below is:
> priv->mbox.txdone_irq = true;
>
> Or am i missed something?
>
>> +};
>> +
>> +static int imx_mu_probe(struct platform_device *pdev)
>> +{
>> +       struct device *dev = &pdev->dev;
>> +       struct resource *iomem;
>> +       struct imx_mu_priv *priv;
>> +       const struct imx_mu_cfg *dcfg;
>> +       unsigned int i, chans;
>> +       int irq, ret;
>> +
>> +       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
>> +       if (!priv)
>> +               return -ENOMEM;
>> +
>> +       dcfg = of_device_get_match_data(dev);
>> +       if (!dcfg)
>> +               return -EINVAL;
>> +
>> +       priv->dcfg = dcfg;
>> +       priv->dev = dev;
>> +
>> +       iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> +       priv->base = devm_ioremap_resource(&pdev->dev, iomem);
>> +       if (IS_ERR(priv->base))
>> +               return PTR_ERR(priv->base);
>> +
>> +       irq = platform_get_irq(pdev, 0);
>> +       if (irq <= 0)
>> +               return irq < 0 ? irq : -EINVAL;
>
> Is it possible == 0?
>
>> +
>> +       priv->clk = devm_clk_get(dev, NULL);
>> +       if (IS_ERR(priv->clk)) {
>> +               if (PTR_ERR(priv->clk) == -ENOENT) {
>> +                       priv->clk = NULL;
>> +               } else {
>> +                       dev_err(dev, "Failed to get clock\n");
>
> The line looks not be quite meaningful as it may be defer probe.
>
>> +                       return PTR_ERR(priv->clk);
>> +               }
>> +       }
>> +
>> +       ret = clk_prepare_enable(priv->clk);
>> +       if (ret) {
>> +               dev_err(dev, "Failed to enable clock\n");
>> +               return ret;
>> +       }
>> +
>> +       chans = min(dcfg->chans, IMX_MU_MAX_CHANS);
>> +       /* Initialize channel identifiers */
>> +       for (i = 0; i < chans; i++) {
>> +               struct imx_mu_con_priv *cp = &priv->con_priv[i];
>> +
>> +               cp->bidx = 3 - i;
>> +               cp->idx = i;
>> +               cp->irq = irq;
>> +               priv->mbox_chans[i].con_priv = cp;
>> +       }
>> +
>> +       priv->mbox.dev = dev;
>> +       priv->mbox.ops = &imx_mu_ops;
>> +       priv->mbox.chans = priv->mbox_chans;
>> +       priv->mbox.num_chans = chans;
>> +       priv->mbox.txdone_irq = true;
>> +
>> +       platform_set_drvdata(pdev, priv);
>> +
>> +       if (priv->dcfg->init_hw)
>> +               priv->dcfg->init_hw(priv);
>> +
>> +       return mbox_controller_register(&priv->mbox);
>> +}
>> +
>> +static int imx_mu_remove(struct platform_device *pdev)
>> +{
>> +       struct imx_mu_priv *priv = platform_get_drvdata(pdev);
>> +
>> +       mbox_controller_unregister(&priv->mbox);
>> +       clk_disable_unprepare(priv->clk);
>> +
>> +       return 0;
>> +}
>> +
>> +
>> +static void imx_mu_init_imx7d_a(struct imx_mu_priv *priv)
>> +{
>> +       /* Set default config */
>> +       imx_mu_write(priv, 0, IMX_MU_xCR);
>> +}
>> +
>> +static const struct imx_mu_cfg imx_mu_cfg_imx7d_a = {
>> +       .chans = IMX_MU_MAX_CHANS,
>> +       .init_hw = imx_mu_init_imx7d_a,
>> +};
>> +
>> +static const struct imx_mu_cfg imx_mu_cfg_imx7d_b = {
>> +       .chans = IMX_MU_MAX_CHANS,
>> +};
>> +
>> +static const struct of_device_id imx_mu_dt_ids[] = {
>> +       { .compatible = "fsl,imx7s-mu-a", .data = &imx_mu_cfg_imx7d_a },
>> +       { .compatible = "fsl,imx7s-mu-b", .data = &imx_mu_cfg_imx7d_b },
>> +       { },
>> +};
>> +MODULE_DEVICE_TABLE(of, imx_mu_dt_ids);
>> +
>> +static struct platform_driver imx_mu_driver = {
>> +       .probe          = imx_mu_probe,
>> +       .remove         = imx_mu_remove,
>> +       .driver = {
>> +               .name   = "imx_mu",
>> +               .of_match_table = imx_mu_dt_ids,
>> +       },
>> +};
>> +module_platform_driver(imx_mu_driver);
>> +
>> +MODULE_AUTHOR("Oleksij Rempel <o.rempel@pengutronix.de>");
>> +MODULE_DESCRIPTION("Message Unit driver for i.MX7");
>
> s/i.MX7/i.MX
>
> Regards
> Dong Aisheng
>
>> +MODULE_LICENSE("GPL v2");
>> --
>> 2.17.1
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-clk" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 54+ messages in thread

* [PATCH v1 4/4] mailbox: Add support for i.MX7D messaging unit
@ 2018-06-13 12:24       ` Dong Aisheng
  0 siblings, 0 replies; 54+ messages in thread
From: Dong Aisheng @ 2018-06-13 12:24 UTC (permalink / raw)
  To: linux-arm-kernel

Copy linux-imx at nxp.com and more related guys to comment

On Wed, Jun 13, 2018 at 8:21 PM, Dong Aisheng <dongas86@gmail.com> wrote:
> Hi Oleksij,
>
> On Fri, Jun 1, 2018 at 2:58 PM, Oleksij Rempel <o.rempel@pengutronix.de> wrote:
>> The Mailbox controller is able to send messages (up to 4 32 bit words)
>> between the endpoints.
>
> Could we really be able to send up to 4 42bit words with this driver?
>
> It looks to me the current Mailbox framework is more designed for share mem
> transfer which does not fit i.MX MU well.
>
>>
>> This driver was tested using the mailbox-test driver sending messages
>> between the Cortex-A7 and the Cortex-M4.
>
> Would you please provide a guide on how to test it quickly?
> I may want to give a test.
>
>>
>> Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
>> ---
>>  drivers/mailbox/Kconfig       |   6 +
>>  drivers/mailbox/Makefile      |   2 +
>>  drivers/mailbox/imx-mailbox.c | 289 ++++++++++++++++++++++++++++++++++
>>  3 files changed, 297 insertions(+)
>>  create mode 100644 drivers/mailbox/imx-mailbox.c
>>
>> diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
>> index a2bb27446dce..e1d2738a2e4c 100644
>> --- a/drivers/mailbox/Kconfig
>> +++ b/drivers/mailbox/Kconfig
>> @@ -15,6 +15,12 @@ config ARM_MHU
>>           The controller has 3 mailbox channels, the last of which can be
>>           used in Secure mode only.
>>
>> +config IMX_MBOX
>> +       tristate "iMX Mailbox"
>> +       depends on SOC_IMX7D || COMPILE_TEST
>> +       help
>> +         Mailbox implementation for iMX7D Messaging Unit (MU).
>> +
>>  config PLATFORM_MHU
>>         tristate "Platform MHU Mailbox"
>>         depends on OF
>> diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
>> index cc23c3a43fcd..ba2fe1b6dd62 100644
>> --- a/drivers/mailbox/Makefile
>> +++ b/drivers/mailbox/Makefile
>> @@ -7,6 +7,8 @@ obj-$(CONFIG_MAILBOX_TEST)      += mailbox-test.o
>>
>>  obj-$(CONFIG_ARM_MHU)  += arm_mhu.o
>>
>> +obj-$(CONFIG_IMX_MBOX) += imx-mailbox.o
>> +
>>  obj-$(CONFIG_PLATFORM_MHU)     += platform_mhu.o
>>
>>  obj-$(CONFIG_PL320_MBOX)       += pl320-ipc.o
>> diff --git a/drivers/mailbox/imx-mailbox.c b/drivers/mailbox/imx-mailbox.c
>> new file mode 100644
>> index 000000000000..2bc9f11393b1
>> --- /dev/null
>> +++ b/drivers/mailbox/imx-mailbox.c
>> @@ -0,0 +1,289 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Copyright (c) 2018 Pengutronix, Oleksij Rempel <o.rempel@pengutronix.de>
>> + */
>> +
>> +#include <linux/clk.h>
>> +#include <linux/interrupt.h>
>> +#include <linux/io.h>
>> +#include <linux/kernel.h>
>> +#include <linux/mailbox_controller.h>
>> +#include <linux/module.h>
>> +#include <linux/of_device.h>
>> +
>> +/* Transmit Register */
>> +#define IMX_MU_xTRn(x)         (0x00 + 4 * (x))
>> +/* Receive Register */
>> +#define IMX_MU_xRRn(x)         (0x10 + 4 * (x))
>> +/* Status Register */
>> +#define IMX_MU_xSR             0x20
>> +#define IMX_MU_xSR_TEn(x)      BIT(20 + (x))
>> +#define IMX_MU_xSR_RFn(x)      BIT(24 + (x))
>> +#define IMX_MU_xSR_BRDIP       BIT(9)
>> +
>> +/* Control Register */
>> +#define IMX_MU_xCR             0x24
>> +/* Transmit Interrupt Enable */
>> +#define IMX_MU_xCR_TIEn(x)     BIT(20 + (x))
>> +/* Receive Interrupt Enable */
>> +#define IMX_MU_xCR_RIEn(x)     BIT(24 + (x))
>> +
>> +#define IMX_MU_MAX_CHANS       4u
>> +
>> +struct imx_mu_priv;
>> +
>> +struct imx_mu_cfg {
>> +       unsigned int            chans;
>> +       void (*init_hw)(struct imx_mu_priv *priv);
>> +};
>> +
>> +struct imx_mu_con_priv {
>> +       int                     irq;
>> +       unsigned int            bidx;
>> +       unsigned int            idx;
>> +};
>> +
>> +struct imx_mu_priv {
>> +       struct device           *dev;
>> +       const struct imx_mu_cfg *dcfg;
>> +       void __iomem            *base;
>> +
>> +       struct mbox_controller  mbox;
>> +       struct mbox_chan        mbox_chans[IMX_MU_MAX_CHANS];
>> +
>> +       struct imx_mu_con_priv  con_priv[IMX_MU_MAX_CHANS];
>> +       struct clk              *clk;
>> +};
>> +
>> +static struct imx_mu_priv *to_imx_mu_priv(struct mbox_controller *mbox)
>> +{
>> +       return container_of(mbox, struct imx_mu_priv, mbox);
>> +}
>> +
>> +static void imx_mu_write(struct imx_mu_priv *priv, u32 val, u32 offs)
>> +{
>> +       iowrite32(val, priv->base + offs);
>> +}
>> +
>> +static u32 imx_mu_read(struct imx_mu_priv *priv, u32 offs)
>> +{
>> +       return ioread32(priv->base + offs);
>> +}
>> +
>> +static u32 imx_mu_rmw(struct imx_mu_priv *priv, u32 offs, u32 set, u32 clr)
>> +{
>> +       u32 val;
>> +
>> +       val = imx_mu_read(priv, offs);
>> +       val &= ~clr;
>> +       val |= set;
>> +       imx_mu_write(priv, val, offs);
>> +
>> +       return val;
>> +}
>> +
>> +static irqreturn_t imx_mu_isr(int irq, void *p)
>> +{
>> +       struct mbox_chan *chan = p;
>> +       struct imx_mu_con_priv *cp = chan->con_priv;
>> +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
>
> Please do in reversed order from long to short
>
>> +
>> +       u32 val, dat;
>> +
>> +       val = imx_mu_read(priv, IMX_MU_xSR);
>> +       val &= IMX_MU_xSR_TEn(cp->bidx) | IMX_MU_xSR_RFn(cp->bidx);
>> +       if (!val)
>> +               return IRQ_NONE;
>> +
>> +       if (val & IMX_MU_xSR_TEn(cp->bidx)) {
>> +               imx_mu_rmw(priv, IMX_MU_xCR, 0, IMX_MU_xCR_TIEn(cp->bidx));
>> +               mbox_chan_txdone(chan, 0);
>> +       }
>> +
>> +       if (val & IMX_MU_xSR_RFn(cp->bidx)) {
>> +               dat = imx_mu_read(priv, IMX_MU_xRRn(cp->idx));
>> +               mbox_chan_received_data(chan, (void *)&dat);
>> +       }
>> +
>> +       return IRQ_HANDLED;
>> +}
>> +
>> +static bool imx_mu_last_tx_done(struct mbox_chan *chan)
>> +{
>> +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
>> +       struct imx_mu_con_priv *cp = chan->con_priv;
>> +       u32 val;
>> +
>> +       val = imx_mu_read(priv, IMX_MU_xSR);
>> +       /* test if transmit register is empty */
>> +       return (!(val & IMX_MU_xSR_TEn(cp->bidx)));
>> +}
>> +
>> +static int imx_mu_send_data(struct mbox_chan *chan, void *data)
>> +{
>> +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
>> +       struct imx_mu_con_priv *cp = chan->con_priv;
>> +       u32 *arg = data;
>> +
>> +       if (imx_mu_last_tx_done(chan))
>
> return true for tx_done?
> Or maybe better imx_mu_is_busy?
>
>> +               return -EBUSY;
>> +
>> +       imx_mu_write(priv, *arg, IMX_MU_xTRn(cp->idx));
>> +       imx_mu_rmw(priv, IMX_MU_xCR, IMX_MU_xSR_TEn(cp->bidx), 0);
>> +
>> +       return 0;
>> +}
>> +
>> +static int imx_mu_startup(struct mbox_chan *chan)
>> +{
>> +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
>> +       struct imx_mu_con_priv *cp = chan->con_priv;
>> +       int ret;
>> +
>> +       ret = request_irq(cp->irq, imx_mu_isr,
>> +                         IRQF_SHARED, "imx_mu_chan", chan);
>
> This looks me to a bit strange as all virtual channels interrupts
> line actually are the same. And we request that same irq line
> repeatedly here with the same irq handler.
>
>> +       if (ret) {
>> +               dev_err(chan->mbox->dev,
>> +                       "Unable to acquire IRQ %d\n", cp->irq);
>> +               return ret;
>> +       }
>> +
>> +       imx_mu_rmw(priv, IMX_MU_xCR, IMX_MU_xCR_RIEn(cp->bidx), 0);
>> +
>> +       return 0;
>> +}
>> +
>> +static void imx_mu_shutdown(struct mbox_chan *chan)
>> +{
>> +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
>> +       struct imx_mu_con_priv *cp = chan->con_priv;
>> +
>> +       imx_mu_rmw(priv, IMX_MU_xCR, 0,
>> +                  IMX_MU_xCR_TIEn(cp->bidx) | IMX_MU_xCR_RIEn(cp->bidx));
>> +
>> +       free_irq(cp->irq, chan);
>> +}
>> +
>> +static const struct mbox_chan_ops imx_mu_ops = {
>> +       .send_data = imx_mu_send_data,
>> +       .startup = imx_mu_startup,
>> +       .shutdown = imx_mu_shutdown,
>> +       .last_tx_done = imx_mu_last_tx_done,
>
> Do we really need this?
> Looking at the code, it seems .last_tx_done() is only called for polling mode.
> But what you set below is:
> priv->mbox.txdone_irq = true;
>
> Or am i missed something?
>
>> +};
>> +
>> +static int imx_mu_probe(struct platform_device *pdev)
>> +{
>> +       struct device *dev = &pdev->dev;
>> +       struct resource *iomem;
>> +       struct imx_mu_priv *priv;
>> +       const struct imx_mu_cfg *dcfg;
>> +       unsigned int i, chans;
>> +       int irq, ret;
>> +
>> +       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
>> +       if (!priv)
>> +               return -ENOMEM;
>> +
>> +       dcfg = of_device_get_match_data(dev);
>> +       if (!dcfg)
>> +               return -EINVAL;
>> +
>> +       priv->dcfg = dcfg;
>> +       priv->dev = dev;
>> +
>> +       iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> +       priv->base = devm_ioremap_resource(&pdev->dev, iomem);
>> +       if (IS_ERR(priv->base))
>> +               return PTR_ERR(priv->base);
>> +
>> +       irq = platform_get_irq(pdev, 0);
>> +       if (irq <= 0)
>> +               return irq < 0 ? irq : -EINVAL;
>
> Is it possible == 0?
>
>> +
>> +       priv->clk = devm_clk_get(dev, NULL);
>> +       if (IS_ERR(priv->clk)) {
>> +               if (PTR_ERR(priv->clk) == -ENOENT) {
>> +                       priv->clk = NULL;
>> +               } else {
>> +                       dev_err(dev, "Failed to get clock\n");
>
> The line looks not be quite meaningful as it may be defer probe.
>
>> +                       return PTR_ERR(priv->clk);
>> +               }
>> +       }
>> +
>> +       ret = clk_prepare_enable(priv->clk);
>> +       if (ret) {
>> +               dev_err(dev, "Failed to enable clock\n");
>> +               return ret;
>> +       }
>> +
>> +       chans = min(dcfg->chans, IMX_MU_MAX_CHANS);
>> +       /* Initialize channel identifiers */
>> +       for (i = 0; i < chans; i++) {
>> +               struct imx_mu_con_priv *cp = &priv->con_priv[i];
>> +
>> +               cp->bidx = 3 - i;
>> +               cp->idx = i;
>> +               cp->irq = irq;
>> +               priv->mbox_chans[i].con_priv = cp;
>> +       }
>> +
>> +       priv->mbox.dev = dev;
>> +       priv->mbox.ops = &imx_mu_ops;
>> +       priv->mbox.chans = priv->mbox_chans;
>> +       priv->mbox.num_chans = chans;
>> +       priv->mbox.txdone_irq = true;
>> +
>> +       platform_set_drvdata(pdev, priv);
>> +
>> +       if (priv->dcfg->init_hw)
>> +               priv->dcfg->init_hw(priv);
>> +
>> +       return mbox_controller_register(&priv->mbox);
>> +}
>> +
>> +static int imx_mu_remove(struct platform_device *pdev)
>> +{
>> +       struct imx_mu_priv *priv = platform_get_drvdata(pdev);
>> +
>> +       mbox_controller_unregister(&priv->mbox);
>> +       clk_disable_unprepare(priv->clk);
>> +
>> +       return 0;
>> +}
>> +
>> +
>> +static void imx_mu_init_imx7d_a(struct imx_mu_priv *priv)
>> +{
>> +       /* Set default config */
>> +       imx_mu_write(priv, 0, IMX_MU_xCR);
>> +}
>> +
>> +static const struct imx_mu_cfg imx_mu_cfg_imx7d_a = {
>> +       .chans = IMX_MU_MAX_CHANS,
>> +       .init_hw = imx_mu_init_imx7d_a,
>> +};
>> +
>> +static const struct imx_mu_cfg imx_mu_cfg_imx7d_b = {
>> +       .chans = IMX_MU_MAX_CHANS,
>> +};
>> +
>> +static const struct of_device_id imx_mu_dt_ids[] = {
>> +       { .compatible = "fsl,imx7s-mu-a", .data = &imx_mu_cfg_imx7d_a },
>> +       { .compatible = "fsl,imx7s-mu-b", .data = &imx_mu_cfg_imx7d_b },
>> +       { },
>> +};
>> +MODULE_DEVICE_TABLE(of, imx_mu_dt_ids);
>> +
>> +static struct platform_driver imx_mu_driver = {
>> +       .probe          = imx_mu_probe,
>> +       .remove         = imx_mu_remove,
>> +       .driver = {
>> +               .name   = "imx_mu",
>> +               .of_match_table = imx_mu_dt_ids,
>> +       },
>> +};
>> +module_platform_driver(imx_mu_driver);
>> +
>> +MODULE_AUTHOR("Oleksij Rempel <o.rempel@pengutronix.de>");
>> +MODULE_DESCRIPTION("Message Unit driver for i.MX7");
>
> s/i.MX7/i.MX
>
> Regards
> Dong Aisheng
>
>> +MODULE_LICENSE("GPL v2");
>> --
>> 2.17.1
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-clk" in
>> the body of a message to majordomo at vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v1 4/4] mailbox: Add support for i.MX7D messaging unit
  2018-06-13 12:21     ` Dong Aisheng
  (?)
@ 2018-06-13 12:48       ` Sascha Hauer
  -1 siblings, 0 replies; 54+ messages in thread
From: Sascha Hauer @ 2018-06-13 12:48 UTC (permalink / raw)
  To: Dong Aisheng
  Cc: Mark Rutland, devicetree, Oleksij Rempel, Rob Herring,
	Sascha Hauer, Fabio Estevam, Shawn Guo, linux-clk,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE

On Wed, Jun 13, 2018 at 08:21:10PM +0800, Dong Aisheng wrote:
> Hi Oleksij,
> 
> On Fri, Jun 1, 2018 at 2:58 PM, Oleksij Rempel <o.rempel@pengutronix.de> wrote:
> > The Mailbox controller is able to send messages (up to 4 32 bit words)
> > between the endpoints.
> 
> Could we really be able to send up to 4 42bit words with this driver?
> 
> It looks to me the current Mailbox framework is more designed for share mem
> transfer which does not fit i.MX MU well.

The mailbox framework just defines channels and messages. A message is a
void * which may contain arbitrary data or even no data at all; some
drivers simply ignore the message pointer, so in fact they act as a
doorbell unit only.

There's nothing about shared memory in the mailbox framework, but of
course you can combine a mailbox driver and shared memory to a remote
message mechanism. That could be done with the i.MX MU aswell and would
indeed be a good match for the hardware.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v1 4/4] mailbox: Add support for i.MX7D messaging unit
@ 2018-06-13 12:48       ` Sascha Hauer
  0 siblings, 0 replies; 54+ messages in thread
From: Sascha Hauer @ 2018-06-13 12:48 UTC (permalink / raw)
  To: Dong Aisheng
  Cc: Oleksij Rempel, Shawn Guo, Fabio Estevam, Rob Herring,
	Mark Rutland, Sascha Hauer,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
	devicetree, linux-clk

On Wed, Jun 13, 2018 at 08:21:10PM +0800, Dong Aisheng wrote:
> Hi Oleksij,
> 
> On Fri, Jun 1, 2018 at 2:58 PM, Oleksij Rempel <o.rempel@pengutronix.de> wrote:
> > The Mailbox controller is able to send messages (up to 4 32 bit words)
> > between the endpoints.
> 
> Could we really be able to send up to 4 42bit words with this driver?
> 
> It looks to me the current Mailbox framework is more designed for share mem
> transfer which does not fit i.MX MU well.

The mailbox framework just defines channels and messages. A message is a
void * which may contain arbitrary data or even no data at all; some
drivers simply ignore the message pointer, so in fact they act as a
doorbell unit only.

There's nothing about shared memory in the mailbox framework, but of
course you can combine a mailbox driver and shared memory to a remote
message mechanism. That could be done with the i.MX MU aswell and would
indeed be a good match for the hardware.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 54+ messages in thread

* [PATCH v1 4/4] mailbox: Add support for i.MX7D messaging unit
@ 2018-06-13 12:48       ` Sascha Hauer
  0 siblings, 0 replies; 54+ messages in thread
From: Sascha Hauer @ 2018-06-13 12:48 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jun 13, 2018 at 08:21:10PM +0800, Dong Aisheng wrote:
> Hi Oleksij,
> 
> On Fri, Jun 1, 2018 at 2:58 PM, Oleksij Rempel <o.rempel@pengutronix.de> wrote:
> > The Mailbox controller is able to send messages (up to 4 32 bit words)
> > between the endpoints.
> 
> Could we really be able to send up to 4 42bit words with this driver?
> 
> It looks to me the current Mailbox framework is more designed for share mem
> transfer which does not fit i.MX MU well.

The mailbox framework just defines channels and messages. A message is a
void * which may contain arbitrary data or even no data at all; some
drivers simply ignore the message pointer, so in fact they act as a
doorbell unit only.

There's nothing about shared memory in the mailbox framework, but of
course you can combine a mailbox driver and shared memory to a remote
message mechanism. That could be done with the i.MX MU aswell and would
indeed be a good match for the hardware.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v1 4/4] mailbox: Add support for i.MX7D messaging unit
  2018-06-13 12:48       ` Sascha Hauer
  (?)
@ 2018-06-14  8:23         ` Dong Aisheng
  -1 siblings, 0 replies; 54+ messages in thread
From: Dong Aisheng @ 2018-06-14  8:23 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: Mark Rutland, devicetree, Oleksij Rempel, Rob Herring,
	Sascha Hauer, Fabio Estevam, Shawn Guo, linux-clk,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE

Hi Sascha,

On Wed, Jun 13, 2018 at 8:48 PM, Sascha Hauer <s.hauer@pengutronix.de> wrote:
> On Wed, Jun 13, 2018 at 08:21:10PM +0800, Dong Aisheng wrote:
>> Hi Oleksij,
>>
>> On Fri, Jun 1, 2018 at 2:58 PM, Oleksij Rempel <o.rempel@pengutronix.de> wrote:
>> > The Mailbox controller is able to send messages (up to 4 32 bit words)
>> > between the endpoints.
>>
>> Could we really be able to send up to 4 42bit words with this driver?
>>
>> It looks to me the current Mailbox framework is more designed for share mem
>> transfer which does not fit i.MX MU well.
>
> The mailbox framework just defines channels and messages. A message is a
> void * which may contain arbitrary data or even no data at all; some
> drivers simply ignore the message pointer, so in fact they act as a
> doorbell unit only.
>
> There's nothing about shared memory in the mailbox framework, but of
> course you can combine a mailbox driver and shared memory to a remote
> message mechanism. That could be done with the i.MX MU aswell and would
> indeed be a good match for the hardware.
>

Yes, you're right. My earlier reply is less accurate.
It seems the actual data type is interpreted by the underlying MU driver.

Regards
Dong Aisheng

> Sascha
>
> --
> Pengutronix e.K.                           |                             |
> Industrial Linux Solutions                 | http://www.pengutronix.de/  |
> Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v1 4/4] mailbox: Add support for i.MX7D messaging unit
@ 2018-06-14  8:23         ` Dong Aisheng
  0 siblings, 0 replies; 54+ messages in thread
From: Dong Aisheng @ 2018-06-14  8:23 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: Oleksij Rempel, Shawn Guo, Fabio Estevam, Rob Herring,
	Mark Rutland, Sascha Hauer,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE,
	devicetree, linux-clk

Hi Sascha,

On Wed, Jun 13, 2018 at 8:48 PM, Sascha Hauer <s.hauer@pengutronix.de> wrote:
> On Wed, Jun 13, 2018 at 08:21:10PM +0800, Dong Aisheng wrote:
>> Hi Oleksij,
>>
>> On Fri, Jun 1, 2018 at 2:58 PM, Oleksij Rempel <o.rempel@pengutronix.de> wrote:
>> > The Mailbox controller is able to send messages (up to 4 32 bit words)
>> > between the endpoints.
>>
>> Could we really be able to send up to 4 42bit words with this driver?
>>
>> It looks to me the current Mailbox framework is more designed for share mem
>> transfer which does not fit i.MX MU well.
>
> The mailbox framework just defines channels and messages. A message is a
> void * which may contain arbitrary data or even no data at all; some
> drivers simply ignore the message pointer, so in fact they act as a
> doorbell unit only.
>
> There's nothing about shared memory in the mailbox framework, but of
> course you can combine a mailbox driver and shared memory to a remote
> message mechanism. That could be done with the i.MX MU aswell and would
> indeed be a good match for the hardware.
>

Yes, you're right. My earlier reply is less accurate.
It seems the actual data type is interpreted by the underlying MU driver.

Regards
Dong Aisheng

> Sascha
>
> --
> Pengutronix e.K.                           |                             |
> Industrial Linux Solutions                 | http://www.pengutronix.de/  |
> Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 54+ messages in thread

* [PATCH v1 4/4] mailbox: Add support for i.MX7D messaging unit
@ 2018-06-14  8:23         ` Dong Aisheng
  0 siblings, 0 replies; 54+ messages in thread
From: Dong Aisheng @ 2018-06-14  8:23 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Sascha,

On Wed, Jun 13, 2018 at 8:48 PM, Sascha Hauer <s.hauer@pengutronix.de> wrote:
> On Wed, Jun 13, 2018 at 08:21:10PM +0800, Dong Aisheng wrote:
>> Hi Oleksij,
>>
>> On Fri, Jun 1, 2018 at 2:58 PM, Oleksij Rempel <o.rempel@pengutronix.de> wrote:
>> > The Mailbox controller is able to send messages (up to 4 32 bit words)
>> > between the endpoints.
>>
>> Could we really be able to send up to 4 42bit words with this driver?
>>
>> It looks to me the current Mailbox framework is more designed for share mem
>> transfer which does not fit i.MX MU well.
>
> The mailbox framework just defines channels and messages. A message is a
> void * which may contain arbitrary data or even no data at all; some
> drivers simply ignore the message pointer, so in fact they act as a
> doorbell unit only.
>
> There's nothing about shared memory in the mailbox framework, but of
> course you can combine a mailbox driver and shared memory to a remote
> message mechanism. That could be done with the i.MX MU aswell and would
> indeed be a good match for the hardware.
>

Yes, you're right. My earlier reply is less accurate.
It seems the actual data type is interpreted by the underlying MU driver.

Regards
Dong Aisheng

> Sascha
>
> --
> Pengutronix e.K.                           |                             |
> Industrial Linux Solutions                 | http://www.pengutronix.de/  |
> Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
> Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v1 4/4] mailbox: Add support for i.MX7D messaging unit
  2018-06-13 12:21     ` Dong Aisheng
  (?)
@ 2018-06-14 10:24       ` Oleksij Rempel
  -1 siblings, 0 replies; 54+ messages in thread
From: Oleksij Rempel @ 2018-06-14 10:24 UTC (permalink / raw)
  To: Dong Aisheng
  Cc: Mark Rutland, devicetree, Rob Herring, Sascha Hauer,
	Fabio Estevam, Shawn Guo, linux-clk,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE


[-- Attachment #1.1: Type: text/plain, Size: 13807 bytes --]

On Wed, Jun 13, 2018 at 08:21:10PM +0800, Dong Aisheng wrote:
> Hi Oleksij,
> 
> On Fri, Jun 1, 2018 at 2:58 PM, Oleksij Rempel <o.rempel@pengutronix.de> wrote:
> > The Mailbox controller is able to send messages (up to 4 32 bit words)
> > between the endpoints.
> 
> Could we really be able to send up to 4 42bit words with this driver?
> 
> It looks to me the current Mailbox framework is more designed for share mem
> transfer which does not fit i.MX MU well.

It is possible to set mbox_chan_txdone as soon as one of 4 regs is
written. Even more, it looks like, it should be possible to make a 8
channel mailbox on top of one MU. But i don't have any reason or use
case to implement and test it now.

> >
> > This driver was tested using the mailbox-test driver sending messages
> > between the Cortex-A7 and the Cortex-M4.
> 
> Would you please provide a guide on how to test it quickly?
> I may want to give a test.

I use Linux on both side. The linux on M4 is booted over remoteproc.
Currently not all needed parts are upstream. I'll prepare a BSP to build
all components as soon as possible.

> 
> >
> > Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
> > ---
> >  drivers/mailbox/Kconfig       |   6 +
> >  drivers/mailbox/Makefile      |   2 +
> >  drivers/mailbox/imx-mailbox.c | 289 ++++++++++++++++++++++++++++++++++
> >  3 files changed, 297 insertions(+)
> >  create mode 100644 drivers/mailbox/imx-mailbox.c
> >
> > diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
> > index a2bb27446dce..e1d2738a2e4c 100644
> > --- a/drivers/mailbox/Kconfig
> > +++ b/drivers/mailbox/Kconfig
> > @@ -15,6 +15,12 @@ config ARM_MHU
> >           The controller has 3 mailbox channels, the last of which can be
> >           used in Secure mode only.
> >
> > +config IMX_MBOX
> > +       tristate "iMX Mailbox"
> > +       depends on SOC_IMX7D || COMPILE_TEST
> > +       help
> > +         Mailbox implementation for iMX7D Messaging Unit (MU).
> > +
> >  config PLATFORM_MHU
> >         tristate "Platform MHU Mailbox"
> >         depends on OF
> > diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
> > index cc23c3a43fcd..ba2fe1b6dd62 100644
> > --- a/drivers/mailbox/Makefile
> > +++ b/drivers/mailbox/Makefile
> > @@ -7,6 +7,8 @@ obj-$(CONFIG_MAILBOX_TEST)      += mailbox-test.o
> >
> >  obj-$(CONFIG_ARM_MHU)  += arm_mhu.o
> >
> > +obj-$(CONFIG_IMX_MBOX) += imx-mailbox.o
> > +
> >  obj-$(CONFIG_PLATFORM_MHU)     += platform_mhu.o
> >
> >  obj-$(CONFIG_PL320_MBOX)       += pl320-ipc.o
> > diff --git a/drivers/mailbox/imx-mailbox.c b/drivers/mailbox/imx-mailbox.c
> > new file mode 100644
> > index 000000000000..2bc9f11393b1
> > --- /dev/null
> > +++ b/drivers/mailbox/imx-mailbox.c
> > @@ -0,0 +1,289 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Copyright (c) 2018 Pengutronix, Oleksij Rempel <o.rempel@pengutronix.de>
> > + */
> > +
> > +#include <linux/clk.h>
> > +#include <linux/interrupt.h>
> > +#include <linux/io.h>
> > +#include <linux/kernel.h>
> > +#include <linux/mailbox_controller.h>
> > +#include <linux/module.h>
> > +#include <linux/of_device.h>
> > +
> > +/* Transmit Register */
> > +#define IMX_MU_xTRn(x)         (0x00 + 4 * (x))
> > +/* Receive Register */
> > +#define IMX_MU_xRRn(x)         (0x10 + 4 * (x))
> > +/* Status Register */
> > +#define IMX_MU_xSR             0x20
> > +#define IMX_MU_xSR_TEn(x)      BIT(20 + (x))
> > +#define IMX_MU_xSR_RFn(x)      BIT(24 + (x))
> > +#define IMX_MU_xSR_BRDIP       BIT(9)
> > +
> > +/* Control Register */
> > +#define IMX_MU_xCR             0x24
> > +/* Transmit Interrupt Enable */
> > +#define IMX_MU_xCR_TIEn(x)     BIT(20 + (x))
> > +/* Receive Interrupt Enable */
> > +#define IMX_MU_xCR_RIEn(x)     BIT(24 + (x))
> > +
> > +#define IMX_MU_MAX_CHANS       4u
> > +
> > +struct imx_mu_priv;
> > +
> > +struct imx_mu_cfg {
> > +       unsigned int            chans;
> > +       void (*init_hw)(struct imx_mu_priv *priv);
> > +};
> > +
> > +struct imx_mu_con_priv {
> > +       int                     irq;
> > +       unsigned int            bidx;
> > +       unsigned int            idx;
> > +};
> > +
> > +struct imx_mu_priv {
> > +       struct device           *dev;
> > +       const struct imx_mu_cfg *dcfg;
> > +       void __iomem            *base;
> > +
> > +       struct mbox_controller  mbox;
> > +       struct mbox_chan        mbox_chans[IMX_MU_MAX_CHANS];
> > +
> > +       struct imx_mu_con_priv  con_priv[IMX_MU_MAX_CHANS];
> > +       struct clk              *clk;
> > +};
> > +
> > +static struct imx_mu_priv *to_imx_mu_priv(struct mbox_controller *mbox)
> > +{
> > +       return container_of(mbox, struct imx_mu_priv, mbox);
> > +}
> > +
> > +static void imx_mu_write(struct imx_mu_priv *priv, u32 val, u32 offs)
> > +{
> > +       iowrite32(val, priv->base + offs);
> > +}
> > +
> > +static u32 imx_mu_read(struct imx_mu_priv *priv, u32 offs)
> > +{
> > +       return ioread32(priv->base + offs);
> > +}
> > +
> > +static u32 imx_mu_rmw(struct imx_mu_priv *priv, u32 offs, u32 set, u32 clr)
> > +{
> > +       u32 val;
> > +
> > +       val = imx_mu_read(priv, offs);
> > +       val &= ~clr;
> > +       val |= set;
> > +       imx_mu_write(priv, val, offs);
> > +
> > +       return val;
> > +}
> > +
> > +static irqreturn_t imx_mu_isr(int irq, void *p)
> > +{
> > +       struct mbox_chan *chan = p;
> > +       struct imx_mu_con_priv *cp = chan->con_priv;
> > +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
> 
> Please do in reversed order from long to short

done

> > +
> > +       u32 val, dat;
> > +
> > +       val = imx_mu_read(priv, IMX_MU_xSR);
> > +       val &= IMX_MU_xSR_TEn(cp->bidx) | IMX_MU_xSR_RFn(cp->bidx);
> > +       if (!val)
> > +               return IRQ_NONE;
> > +
> > +       if (val & IMX_MU_xSR_TEn(cp->bidx)) {
> > +               imx_mu_rmw(priv, IMX_MU_xCR, 0, IMX_MU_xCR_TIEn(cp->bidx));
> > +               mbox_chan_txdone(chan, 0);
> > +       }
> > +
> > +       if (val & IMX_MU_xSR_RFn(cp->bidx)) {
> > +               dat = imx_mu_read(priv, IMX_MU_xRRn(cp->idx));
> > +               mbox_chan_received_data(chan, (void *)&dat);
> > +       }
> > +
> > +       return IRQ_HANDLED;
> > +}
> > +
> > +static bool imx_mu_last_tx_done(struct mbox_chan *chan)
> > +{
> > +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
> > +       struct imx_mu_con_priv *cp = chan->con_priv;
> > +       u32 val;
> > +
> > +       val = imx_mu_read(priv, IMX_MU_xSR);
> > +       /* test if transmit register is empty */
> > +       return (!(val & IMX_MU_xSR_TEn(cp->bidx)));
> > +}
> > +
> > +static int imx_mu_send_data(struct mbox_chan *chan, void *data)
> > +{
> > +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
> > +       struct imx_mu_con_priv *cp = chan->con_priv;
> > +       u32 *arg = data;
> > +
> > +       if (imx_mu_last_tx_done(chan))
> 
> return true for tx_done?
> Or maybe better imx_mu_is_busy?

I'll the name and rework the logic. For polling, if this will be ever
used.

> > +               return -EBUSY;
> > +
> > +       imx_mu_write(priv, *arg, IMX_MU_xTRn(cp->idx));
> > +       imx_mu_rmw(priv, IMX_MU_xCR, IMX_MU_xSR_TEn(cp->bidx), 0);
> > +
> > +       return 0;
> > +}
> > +
> > +static int imx_mu_startup(struct mbox_chan *chan)
> > +{
> > +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
> > +       struct imx_mu_con_priv *cp = chan->con_priv;
> > +       int ret;
> > +
> > +       ret = request_irq(cp->irq, imx_mu_isr,
> > +                         IRQF_SHARED, "imx_mu_chan", chan);
> 
> This looks me to a bit strange as all virtual channels interrupts
> line actually are the same. And we request that same irq line
> repeatedly here with the same irq handler.

Why not? Code is simple and performance should not be noticeable.

> > +       if (ret) {
> > +               dev_err(chan->mbox->dev,
> > +                       "Unable to acquire IRQ %d\n", cp->irq);
> > +               return ret;
> > +       }
> > +
> > +       imx_mu_rmw(priv, IMX_MU_xCR, IMX_MU_xCR_RIEn(cp->bidx), 0);
> > +
> > +       return 0;
> > +}
> > +
> > +static void imx_mu_shutdown(struct mbox_chan *chan)
> > +{
> > +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
> > +       struct imx_mu_con_priv *cp = chan->con_priv;
> > +
> > +       imx_mu_rmw(priv, IMX_MU_xCR, 0,
> > +                  IMX_MU_xCR_TIEn(cp->bidx) | IMX_MU_xCR_RIEn(cp->bidx));
> > +
> > +       free_irq(cp->irq, chan);
> > +}
> > +
> > +static const struct mbox_chan_ops imx_mu_ops = {
> > +       .send_data = imx_mu_send_data,
> > +       .startup = imx_mu_startup,
> > +       .shutdown = imx_mu_shutdown,
> > +       .last_tx_done = imx_mu_last_tx_done,
> 
> Do we really need this?
> Looking at the code, it seems .last_tx_done() is only called for polling mode.
> But what you set below is:
> priv->mbox.txdone_irq = true;
> 
> Or am i missed something?

no. I'll remove it for now.

> 
> > +};
> > +
> > +static int imx_mu_probe(struct platform_device *pdev)
> > +{
> > +       struct device *dev = &pdev->dev;
> > +       struct resource *iomem;
> > +       struct imx_mu_priv *priv;
> > +       const struct imx_mu_cfg *dcfg;
> > +       unsigned int i, chans;
> > +       int irq, ret;
> > +
> > +       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> > +       if (!priv)
> > +               return -ENOMEM;
> > +
> > +       dcfg = of_device_get_match_data(dev);
> > +       if (!dcfg)
> > +               return -EINVAL;
> > +
> > +       priv->dcfg = dcfg;
> > +       priv->dev = dev;
> > +
> > +       iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > +       priv->base = devm_ioremap_resource(&pdev->dev, iomem);
> > +       if (IS_ERR(priv->base))
> > +               return PTR_ERR(priv->base);
> > +
> > +       irq = platform_get_irq(pdev, 0);
> > +       if (irq <= 0)
> > +               return irq < 0 ? irq : -EINVAL;
> 
> Is it possible == 0?

no:
https://elixir.bootlin.com/linux/latest/source/drivers/base/platform.c#L86
or do I miss some thing?

> > +
> > +       priv->clk = devm_clk_get(dev, NULL);
> > +       if (IS_ERR(priv->clk)) {
> > +               if (PTR_ERR(priv->clk) == -ENOENT) {
> > +                       priv->clk = NULL;
> > +               } else {
> > +                       dev_err(dev, "Failed to get clock\n");
> 
> The line looks not be quite meaningful as it may be defer probe.

What is your suggestion?

> > +                       return PTR_ERR(priv->clk);
> > +               }
> > +       }
> > +
> > +       ret = clk_prepare_enable(priv->clk);
> > +       if (ret) {
> > +               dev_err(dev, "Failed to enable clock\n");
> > +               return ret;
> > +       }
> > +
> > +       chans = min(dcfg->chans, IMX_MU_MAX_CHANS);
> > +       /* Initialize channel identifiers */
> > +       for (i = 0; i < chans; i++) {
> > +               struct imx_mu_con_priv *cp = &priv->con_priv[i];
> > +
> > +               cp->bidx = 3 - i;
> > +               cp->idx = i;
> > +               cp->irq = irq;
> > +               priv->mbox_chans[i].con_priv = cp;
> > +       }
> > +
> > +       priv->mbox.dev = dev;
> > +       priv->mbox.ops = &imx_mu_ops;
> > +       priv->mbox.chans = priv->mbox_chans;
> > +       priv->mbox.num_chans = chans;
> > +       priv->mbox.txdone_irq = true;
> > +
> > +       platform_set_drvdata(pdev, priv);
> > +
> > +       if (priv->dcfg->init_hw)
> > +               priv->dcfg->init_hw(priv);
> > +
> > +       return mbox_controller_register(&priv->mbox);
> > +}
> > +
> > +static int imx_mu_remove(struct platform_device *pdev)
> > +{
> > +       struct imx_mu_priv *priv = platform_get_drvdata(pdev);
> > +
> > +       mbox_controller_unregister(&priv->mbox);
> > +       clk_disable_unprepare(priv->clk);
> > +
> > +       return 0;
> > +}
> > +
> > +
> > +static void imx_mu_init_imx7d_a(struct imx_mu_priv *priv)
> > +{
> > +       /* Set default config */
> > +       imx_mu_write(priv, 0, IMX_MU_xCR);
> > +}
> > +
> > +static const struct imx_mu_cfg imx_mu_cfg_imx7d_a = {
> > +       .chans = IMX_MU_MAX_CHANS,
> > +       .init_hw = imx_mu_init_imx7d_a,
> > +};
> > +
> > +static const struct imx_mu_cfg imx_mu_cfg_imx7d_b = {
> > +       .chans = IMX_MU_MAX_CHANS,
> > +};
> > +
> > +static const struct of_device_id imx_mu_dt_ids[] = {
> > +       { .compatible = "fsl,imx7s-mu-a", .data = &imx_mu_cfg_imx7d_a },
> > +       { .compatible = "fsl,imx7s-mu-b", .data = &imx_mu_cfg_imx7d_b },
> > +       { },
> > +};
> > +MODULE_DEVICE_TABLE(of, imx_mu_dt_ids);
> > +
> > +static struct platform_driver imx_mu_driver = {
> > +       .probe          = imx_mu_probe,
> > +       .remove         = imx_mu_remove,
> > +       .driver = {
> > +               .name   = "imx_mu",
> > +               .of_match_table = imx_mu_dt_ids,
> > +       },
> > +};
> > +module_platform_driver(imx_mu_driver);
> > +
> > +MODULE_AUTHOR("Oleksij Rempel <o.rempel@pengutronix.de>");
> > +MODULE_DESCRIPTION("Message Unit driver for i.MX7");
> 
> s/i.MX7/i.MX

ok

> Regards
> Dong Aisheng

thank you for review.

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

[-- Attachment #2: Type: text/plain, Size: 176 bytes --]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v1 4/4] mailbox: Add support for i.MX7D messaging unit
@ 2018-06-14 10:24       ` Oleksij Rempel
  0 siblings, 0 replies; 54+ messages in thread
From: Oleksij Rempel @ 2018-06-14 10:24 UTC (permalink / raw)
  To: Dong Aisheng
  Cc: Mark Rutland, devicetree, Rob Herring, Sascha Hauer,
	Fabio Estevam, Shawn Guo, linux-clk,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE

[-- Attachment #1: Type: text/plain, Size: 13807 bytes --]

On Wed, Jun 13, 2018 at 08:21:10PM +0800, Dong Aisheng wrote:
> Hi Oleksij,
> 
> On Fri, Jun 1, 2018 at 2:58 PM, Oleksij Rempel <o.rempel@pengutronix.de> wrote:
> > The Mailbox controller is able to send messages (up to 4 32 bit words)
> > between the endpoints.
> 
> Could we really be able to send up to 4 42bit words with this driver?
> 
> It looks to me the current Mailbox framework is more designed for share mem
> transfer which does not fit i.MX MU well.

It is possible to set mbox_chan_txdone as soon as one of 4 regs is
written. Even more, it looks like, it should be possible to make a 8
channel mailbox on top of one MU. But i don't have any reason or use
case to implement and test it now.

> >
> > This driver was tested using the mailbox-test driver sending messages
> > between the Cortex-A7 and the Cortex-M4.
> 
> Would you please provide a guide on how to test it quickly?
> I may want to give a test.

I use Linux on both side. The linux on M4 is booted over remoteproc.
Currently not all needed parts are upstream. I'll prepare a BSP to build
all components as soon as possible.

> 
> >
> > Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
> > ---
> >  drivers/mailbox/Kconfig       |   6 +
> >  drivers/mailbox/Makefile      |   2 +
> >  drivers/mailbox/imx-mailbox.c | 289 ++++++++++++++++++++++++++++++++++
> >  3 files changed, 297 insertions(+)
> >  create mode 100644 drivers/mailbox/imx-mailbox.c
> >
> > diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
> > index a2bb27446dce..e1d2738a2e4c 100644
> > --- a/drivers/mailbox/Kconfig
> > +++ b/drivers/mailbox/Kconfig
> > @@ -15,6 +15,12 @@ config ARM_MHU
> >           The controller has 3 mailbox channels, the last of which can be
> >           used in Secure mode only.
> >
> > +config IMX_MBOX
> > +       tristate "iMX Mailbox"
> > +       depends on SOC_IMX7D || COMPILE_TEST
> > +       help
> > +         Mailbox implementation for iMX7D Messaging Unit (MU).
> > +
> >  config PLATFORM_MHU
> >         tristate "Platform MHU Mailbox"
> >         depends on OF
> > diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
> > index cc23c3a43fcd..ba2fe1b6dd62 100644
> > --- a/drivers/mailbox/Makefile
> > +++ b/drivers/mailbox/Makefile
> > @@ -7,6 +7,8 @@ obj-$(CONFIG_MAILBOX_TEST)      += mailbox-test.o
> >
> >  obj-$(CONFIG_ARM_MHU)  += arm_mhu.o
> >
> > +obj-$(CONFIG_IMX_MBOX) += imx-mailbox.o
> > +
> >  obj-$(CONFIG_PLATFORM_MHU)     += platform_mhu.o
> >
> >  obj-$(CONFIG_PL320_MBOX)       += pl320-ipc.o
> > diff --git a/drivers/mailbox/imx-mailbox.c b/drivers/mailbox/imx-mailbox.c
> > new file mode 100644
> > index 000000000000..2bc9f11393b1
> > --- /dev/null
> > +++ b/drivers/mailbox/imx-mailbox.c
> > @@ -0,0 +1,289 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Copyright (c) 2018 Pengutronix, Oleksij Rempel <o.rempel@pengutronix.de>
> > + */
> > +
> > +#include <linux/clk.h>
> > +#include <linux/interrupt.h>
> > +#include <linux/io.h>
> > +#include <linux/kernel.h>
> > +#include <linux/mailbox_controller.h>
> > +#include <linux/module.h>
> > +#include <linux/of_device.h>
> > +
> > +/* Transmit Register */
> > +#define IMX_MU_xTRn(x)         (0x00 + 4 * (x))
> > +/* Receive Register */
> > +#define IMX_MU_xRRn(x)         (0x10 + 4 * (x))
> > +/* Status Register */
> > +#define IMX_MU_xSR             0x20
> > +#define IMX_MU_xSR_TEn(x)      BIT(20 + (x))
> > +#define IMX_MU_xSR_RFn(x)      BIT(24 + (x))
> > +#define IMX_MU_xSR_BRDIP       BIT(9)
> > +
> > +/* Control Register */
> > +#define IMX_MU_xCR             0x24
> > +/* Transmit Interrupt Enable */
> > +#define IMX_MU_xCR_TIEn(x)     BIT(20 + (x))
> > +/* Receive Interrupt Enable */
> > +#define IMX_MU_xCR_RIEn(x)     BIT(24 + (x))
> > +
> > +#define IMX_MU_MAX_CHANS       4u
> > +
> > +struct imx_mu_priv;
> > +
> > +struct imx_mu_cfg {
> > +       unsigned int            chans;
> > +       void (*init_hw)(struct imx_mu_priv *priv);
> > +};
> > +
> > +struct imx_mu_con_priv {
> > +       int                     irq;
> > +       unsigned int            bidx;
> > +       unsigned int            idx;
> > +};
> > +
> > +struct imx_mu_priv {
> > +       struct device           *dev;
> > +       const struct imx_mu_cfg *dcfg;
> > +       void __iomem            *base;
> > +
> > +       struct mbox_controller  mbox;
> > +       struct mbox_chan        mbox_chans[IMX_MU_MAX_CHANS];
> > +
> > +       struct imx_mu_con_priv  con_priv[IMX_MU_MAX_CHANS];
> > +       struct clk              *clk;
> > +};
> > +
> > +static struct imx_mu_priv *to_imx_mu_priv(struct mbox_controller *mbox)
> > +{
> > +       return container_of(mbox, struct imx_mu_priv, mbox);
> > +}
> > +
> > +static void imx_mu_write(struct imx_mu_priv *priv, u32 val, u32 offs)
> > +{
> > +       iowrite32(val, priv->base + offs);
> > +}
> > +
> > +static u32 imx_mu_read(struct imx_mu_priv *priv, u32 offs)
> > +{
> > +       return ioread32(priv->base + offs);
> > +}
> > +
> > +static u32 imx_mu_rmw(struct imx_mu_priv *priv, u32 offs, u32 set, u32 clr)
> > +{
> > +       u32 val;
> > +
> > +       val = imx_mu_read(priv, offs);
> > +       val &= ~clr;
> > +       val |= set;
> > +       imx_mu_write(priv, val, offs);
> > +
> > +       return val;
> > +}
> > +
> > +static irqreturn_t imx_mu_isr(int irq, void *p)
> > +{
> > +       struct mbox_chan *chan = p;
> > +       struct imx_mu_con_priv *cp = chan->con_priv;
> > +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
> 
> Please do in reversed order from long to short

done

> > +
> > +       u32 val, dat;
> > +
> > +       val = imx_mu_read(priv, IMX_MU_xSR);
> > +       val &= IMX_MU_xSR_TEn(cp->bidx) | IMX_MU_xSR_RFn(cp->bidx);
> > +       if (!val)
> > +               return IRQ_NONE;
> > +
> > +       if (val & IMX_MU_xSR_TEn(cp->bidx)) {
> > +               imx_mu_rmw(priv, IMX_MU_xCR, 0, IMX_MU_xCR_TIEn(cp->bidx));
> > +               mbox_chan_txdone(chan, 0);
> > +       }
> > +
> > +       if (val & IMX_MU_xSR_RFn(cp->bidx)) {
> > +               dat = imx_mu_read(priv, IMX_MU_xRRn(cp->idx));
> > +               mbox_chan_received_data(chan, (void *)&dat);
> > +       }
> > +
> > +       return IRQ_HANDLED;
> > +}
> > +
> > +static bool imx_mu_last_tx_done(struct mbox_chan *chan)
> > +{
> > +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
> > +       struct imx_mu_con_priv *cp = chan->con_priv;
> > +       u32 val;
> > +
> > +       val = imx_mu_read(priv, IMX_MU_xSR);
> > +       /* test if transmit register is empty */
> > +       return (!(val & IMX_MU_xSR_TEn(cp->bidx)));
> > +}
> > +
> > +static int imx_mu_send_data(struct mbox_chan *chan, void *data)
> > +{
> > +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
> > +       struct imx_mu_con_priv *cp = chan->con_priv;
> > +       u32 *arg = data;
> > +
> > +       if (imx_mu_last_tx_done(chan))
> 
> return true for tx_done?
> Or maybe better imx_mu_is_busy?

I'll the name and rework the logic. For polling, if this will be ever
used.

> > +               return -EBUSY;
> > +
> > +       imx_mu_write(priv, *arg, IMX_MU_xTRn(cp->idx));
> > +       imx_mu_rmw(priv, IMX_MU_xCR, IMX_MU_xSR_TEn(cp->bidx), 0);
> > +
> > +       return 0;
> > +}
> > +
> > +static int imx_mu_startup(struct mbox_chan *chan)
> > +{
> > +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
> > +       struct imx_mu_con_priv *cp = chan->con_priv;
> > +       int ret;
> > +
> > +       ret = request_irq(cp->irq, imx_mu_isr,
> > +                         IRQF_SHARED, "imx_mu_chan", chan);
> 
> This looks me to a bit strange as all virtual channels interrupts
> line actually are the same. And we request that same irq line
> repeatedly here with the same irq handler.

Why not? Code is simple and performance should not be noticeable.

> > +       if (ret) {
> > +               dev_err(chan->mbox->dev,
> > +                       "Unable to acquire IRQ %d\n", cp->irq);
> > +               return ret;
> > +       }
> > +
> > +       imx_mu_rmw(priv, IMX_MU_xCR, IMX_MU_xCR_RIEn(cp->bidx), 0);
> > +
> > +       return 0;
> > +}
> > +
> > +static void imx_mu_shutdown(struct mbox_chan *chan)
> > +{
> > +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
> > +       struct imx_mu_con_priv *cp = chan->con_priv;
> > +
> > +       imx_mu_rmw(priv, IMX_MU_xCR, 0,
> > +                  IMX_MU_xCR_TIEn(cp->bidx) | IMX_MU_xCR_RIEn(cp->bidx));
> > +
> > +       free_irq(cp->irq, chan);
> > +}
> > +
> > +static const struct mbox_chan_ops imx_mu_ops = {
> > +       .send_data = imx_mu_send_data,
> > +       .startup = imx_mu_startup,
> > +       .shutdown = imx_mu_shutdown,
> > +       .last_tx_done = imx_mu_last_tx_done,
> 
> Do we really need this?
> Looking at the code, it seems .last_tx_done() is only called for polling mode.
> But what you set below is:
> priv->mbox.txdone_irq = true;
> 
> Or am i missed something?

no. I'll remove it for now.

> 
> > +};
> > +
> > +static int imx_mu_probe(struct platform_device *pdev)
> > +{
> > +       struct device *dev = &pdev->dev;
> > +       struct resource *iomem;
> > +       struct imx_mu_priv *priv;
> > +       const struct imx_mu_cfg *dcfg;
> > +       unsigned int i, chans;
> > +       int irq, ret;
> > +
> > +       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> > +       if (!priv)
> > +               return -ENOMEM;
> > +
> > +       dcfg = of_device_get_match_data(dev);
> > +       if (!dcfg)
> > +               return -EINVAL;
> > +
> > +       priv->dcfg = dcfg;
> > +       priv->dev = dev;
> > +
> > +       iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > +       priv->base = devm_ioremap_resource(&pdev->dev, iomem);
> > +       if (IS_ERR(priv->base))
> > +               return PTR_ERR(priv->base);
> > +
> > +       irq = platform_get_irq(pdev, 0);
> > +       if (irq <= 0)
> > +               return irq < 0 ? irq : -EINVAL;
> 
> Is it possible == 0?

no:
https://elixir.bootlin.com/linux/latest/source/drivers/base/platform.c#L86
or do I miss some thing?

> > +
> > +       priv->clk = devm_clk_get(dev, NULL);
> > +       if (IS_ERR(priv->clk)) {
> > +               if (PTR_ERR(priv->clk) == -ENOENT) {
> > +                       priv->clk = NULL;
> > +               } else {
> > +                       dev_err(dev, "Failed to get clock\n");
> 
> The line looks not be quite meaningful as it may be defer probe.

What is your suggestion?

> > +                       return PTR_ERR(priv->clk);
> > +               }
> > +       }
> > +
> > +       ret = clk_prepare_enable(priv->clk);
> > +       if (ret) {
> > +               dev_err(dev, "Failed to enable clock\n");
> > +               return ret;
> > +       }
> > +
> > +       chans = min(dcfg->chans, IMX_MU_MAX_CHANS);
> > +       /* Initialize channel identifiers */
> > +       for (i = 0; i < chans; i++) {
> > +               struct imx_mu_con_priv *cp = &priv->con_priv[i];
> > +
> > +               cp->bidx = 3 - i;
> > +               cp->idx = i;
> > +               cp->irq = irq;
> > +               priv->mbox_chans[i].con_priv = cp;
> > +       }
> > +
> > +       priv->mbox.dev = dev;
> > +       priv->mbox.ops = &imx_mu_ops;
> > +       priv->mbox.chans = priv->mbox_chans;
> > +       priv->mbox.num_chans = chans;
> > +       priv->mbox.txdone_irq = true;
> > +
> > +       platform_set_drvdata(pdev, priv);
> > +
> > +       if (priv->dcfg->init_hw)
> > +               priv->dcfg->init_hw(priv);
> > +
> > +       return mbox_controller_register(&priv->mbox);
> > +}
> > +
> > +static int imx_mu_remove(struct platform_device *pdev)
> > +{
> > +       struct imx_mu_priv *priv = platform_get_drvdata(pdev);
> > +
> > +       mbox_controller_unregister(&priv->mbox);
> > +       clk_disable_unprepare(priv->clk);
> > +
> > +       return 0;
> > +}
> > +
> > +
> > +static void imx_mu_init_imx7d_a(struct imx_mu_priv *priv)
> > +{
> > +       /* Set default config */
> > +       imx_mu_write(priv, 0, IMX_MU_xCR);
> > +}
> > +
> > +static const struct imx_mu_cfg imx_mu_cfg_imx7d_a = {
> > +       .chans = IMX_MU_MAX_CHANS,
> > +       .init_hw = imx_mu_init_imx7d_a,
> > +};
> > +
> > +static const struct imx_mu_cfg imx_mu_cfg_imx7d_b = {
> > +       .chans = IMX_MU_MAX_CHANS,
> > +};
> > +
> > +static const struct of_device_id imx_mu_dt_ids[] = {
> > +       { .compatible = "fsl,imx7s-mu-a", .data = &imx_mu_cfg_imx7d_a },
> > +       { .compatible = "fsl,imx7s-mu-b", .data = &imx_mu_cfg_imx7d_b },
> > +       { },
> > +};
> > +MODULE_DEVICE_TABLE(of, imx_mu_dt_ids);
> > +
> > +static struct platform_driver imx_mu_driver = {
> > +       .probe          = imx_mu_probe,
> > +       .remove         = imx_mu_remove,
> > +       .driver = {
> > +               .name   = "imx_mu",
> > +               .of_match_table = imx_mu_dt_ids,
> > +       },
> > +};
> > +module_platform_driver(imx_mu_driver);
> > +
> > +MODULE_AUTHOR("Oleksij Rempel <o.rempel@pengutronix.de>");
> > +MODULE_DESCRIPTION("Message Unit driver for i.MX7");
> 
> s/i.MX7/i.MX

ok

> Regards
> Dong Aisheng

thank you for review.

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 54+ messages in thread

* [PATCH v1 4/4] mailbox: Add support for i.MX7D messaging unit
@ 2018-06-14 10:24       ` Oleksij Rempel
  0 siblings, 0 replies; 54+ messages in thread
From: Oleksij Rempel @ 2018-06-14 10:24 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Jun 13, 2018 at 08:21:10PM +0800, Dong Aisheng wrote:
> Hi Oleksij,
> 
> On Fri, Jun 1, 2018 at 2:58 PM, Oleksij Rempel <o.rempel@pengutronix.de> wrote:
> > The Mailbox controller is able to send messages (up to 4 32 bit words)
> > between the endpoints.
> 
> Could we really be able to send up to 4 42bit words with this driver?
> 
> It looks to me the current Mailbox framework is more designed for share mem
> transfer which does not fit i.MX MU well.

It is possible to set mbox_chan_txdone as soon as one of 4 regs is
written. Even more, it looks like, it should be possible to make a 8
channel mailbox on top of one MU. But i don't have any reason or use
case to implement and test it now.

> >
> > This driver was tested using the mailbox-test driver sending messages
> > between the Cortex-A7 and the Cortex-M4.
> 
> Would you please provide a guide on how to test it quickly?
> I may want to give a test.

I use Linux on both side. The linux on M4 is booted over remoteproc.
Currently not all needed parts are upstream. I'll prepare a BSP to build
all components as soon as possible.

> 
> >
> > Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
> > ---
> >  drivers/mailbox/Kconfig       |   6 +
> >  drivers/mailbox/Makefile      |   2 +
> >  drivers/mailbox/imx-mailbox.c | 289 ++++++++++++++++++++++++++++++++++
> >  3 files changed, 297 insertions(+)
> >  create mode 100644 drivers/mailbox/imx-mailbox.c
> >
> > diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
> > index a2bb27446dce..e1d2738a2e4c 100644
> > --- a/drivers/mailbox/Kconfig
> > +++ b/drivers/mailbox/Kconfig
> > @@ -15,6 +15,12 @@ config ARM_MHU
> >           The controller has 3 mailbox channels, the last of which can be
> >           used in Secure mode only.
> >
> > +config IMX_MBOX
> > +       tristate "iMX Mailbox"
> > +       depends on SOC_IMX7D || COMPILE_TEST
> > +       help
> > +         Mailbox implementation for iMX7D Messaging Unit (MU).
> > +
> >  config PLATFORM_MHU
> >         tristate "Platform MHU Mailbox"
> >         depends on OF
> > diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
> > index cc23c3a43fcd..ba2fe1b6dd62 100644
> > --- a/drivers/mailbox/Makefile
> > +++ b/drivers/mailbox/Makefile
> > @@ -7,6 +7,8 @@ obj-$(CONFIG_MAILBOX_TEST)      += mailbox-test.o
> >
> >  obj-$(CONFIG_ARM_MHU)  += arm_mhu.o
> >
> > +obj-$(CONFIG_IMX_MBOX) += imx-mailbox.o
> > +
> >  obj-$(CONFIG_PLATFORM_MHU)     += platform_mhu.o
> >
> >  obj-$(CONFIG_PL320_MBOX)       += pl320-ipc.o
> > diff --git a/drivers/mailbox/imx-mailbox.c b/drivers/mailbox/imx-mailbox.c
> > new file mode 100644
> > index 000000000000..2bc9f11393b1
> > --- /dev/null
> > +++ b/drivers/mailbox/imx-mailbox.c
> > @@ -0,0 +1,289 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Copyright (c) 2018 Pengutronix, Oleksij Rempel <o.rempel@pengutronix.de>
> > + */
> > +
> > +#include <linux/clk.h>
> > +#include <linux/interrupt.h>
> > +#include <linux/io.h>
> > +#include <linux/kernel.h>
> > +#include <linux/mailbox_controller.h>
> > +#include <linux/module.h>
> > +#include <linux/of_device.h>
> > +
> > +/* Transmit Register */
> > +#define IMX_MU_xTRn(x)         (0x00 + 4 * (x))
> > +/* Receive Register */
> > +#define IMX_MU_xRRn(x)         (0x10 + 4 * (x))
> > +/* Status Register */
> > +#define IMX_MU_xSR             0x20
> > +#define IMX_MU_xSR_TEn(x)      BIT(20 + (x))
> > +#define IMX_MU_xSR_RFn(x)      BIT(24 + (x))
> > +#define IMX_MU_xSR_BRDIP       BIT(9)
> > +
> > +/* Control Register */
> > +#define IMX_MU_xCR             0x24
> > +/* Transmit Interrupt Enable */
> > +#define IMX_MU_xCR_TIEn(x)     BIT(20 + (x))
> > +/* Receive Interrupt Enable */
> > +#define IMX_MU_xCR_RIEn(x)     BIT(24 + (x))
> > +
> > +#define IMX_MU_MAX_CHANS       4u
> > +
> > +struct imx_mu_priv;
> > +
> > +struct imx_mu_cfg {
> > +       unsigned int            chans;
> > +       void (*init_hw)(struct imx_mu_priv *priv);
> > +};
> > +
> > +struct imx_mu_con_priv {
> > +       int                     irq;
> > +       unsigned int            bidx;
> > +       unsigned int            idx;
> > +};
> > +
> > +struct imx_mu_priv {
> > +       struct device           *dev;
> > +       const struct imx_mu_cfg *dcfg;
> > +       void __iomem            *base;
> > +
> > +       struct mbox_controller  mbox;
> > +       struct mbox_chan        mbox_chans[IMX_MU_MAX_CHANS];
> > +
> > +       struct imx_mu_con_priv  con_priv[IMX_MU_MAX_CHANS];
> > +       struct clk              *clk;
> > +};
> > +
> > +static struct imx_mu_priv *to_imx_mu_priv(struct mbox_controller *mbox)
> > +{
> > +       return container_of(mbox, struct imx_mu_priv, mbox);
> > +}
> > +
> > +static void imx_mu_write(struct imx_mu_priv *priv, u32 val, u32 offs)
> > +{
> > +       iowrite32(val, priv->base + offs);
> > +}
> > +
> > +static u32 imx_mu_read(struct imx_mu_priv *priv, u32 offs)
> > +{
> > +       return ioread32(priv->base + offs);
> > +}
> > +
> > +static u32 imx_mu_rmw(struct imx_mu_priv *priv, u32 offs, u32 set, u32 clr)
> > +{
> > +       u32 val;
> > +
> > +       val = imx_mu_read(priv, offs);
> > +       val &= ~clr;
> > +       val |= set;
> > +       imx_mu_write(priv, val, offs);
> > +
> > +       return val;
> > +}
> > +
> > +static irqreturn_t imx_mu_isr(int irq, void *p)
> > +{
> > +       struct mbox_chan *chan = p;
> > +       struct imx_mu_con_priv *cp = chan->con_priv;
> > +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
> 
> Please do in reversed order from long to short

done

> > +
> > +       u32 val, dat;
> > +
> > +       val = imx_mu_read(priv, IMX_MU_xSR);
> > +       val &= IMX_MU_xSR_TEn(cp->bidx) | IMX_MU_xSR_RFn(cp->bidx);
> > +       if (!val)
> > +               return IRQ_NONE;
> > +
> > +       if (val & IMX_MU_xSR_TEn(cp->bidx)) {
> > +               imx_mu_rmw(priv, IMX_MU_xCR, 0, IMX_MU_xCR_TIEn(cp->bidx));
> > +               mbox_chan_txdone(chan, 0);
> > +       }
> > +
> > +       if (val & IMX_MU_xSR_RFn(cp->bidx)) {
> > +               dat = imx_mu_read(priv, IMX_MU_xRRn(cp->idx));
> > +               mbox_chan_received_data(chan, (void *)&dat);
> > +       }
> > +
> > +       return IRQ_HANDLED;
> > +}
> > +
> > +static bool imx_mu_last_tx_done(struct mbox_chan *chan)
> > +{
> > +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
> > +       struct imx_mu_con_priv *cp = chan->con_priv;
> > +       u32 val;
> > +
> > +       val = imx_mu_read(priv, IMX_MU_xSR);
> > +       /* test if transmit register is empty */
> > +       return (!(val & IMX_MU_xSR_TEn(cp->bidx)));
> > +}
> > +
> > +static int imx_mu_send_data(struct mbox_chan *chan, void *data)
> > +{
> > +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
> > +       struct imx_mu_con_priv *cp = chan->con_priv;
> > +       u32 *arg = data;
> > +
> > +       if (imx_mu_last_tx_done(chan))
> 
> return true for tx_done?
> Or maybe better imx_mu_is_busy?

I'll the name and rework the logic. For polling, if this will be ever
used.

> > +               return -EBUSY;
> > +
> > +       imx_mu_write(priv, *arg, IMX_MU_xTRn(cp->idx));
> > +       imx_mu_rmw(priv, IMX_MU_xCR, IMX_MU_xSR_TEn(cp->bidx), 0);
> > +
> > +       return 0;
> > +}
> > +
> > +static int imx_mu_startup(struct mbox_chan *chan)
> > +{
> > +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
> > +       struct imx_mu_con_priv *cp = chan->con_priv;
> > +       int ret;
> > +
> > +       ret = request_irq(cp->irq, imx_mu_isr,
> > +                         IRQF_SHARED, "imx_mu_chan", chan);
> 
> This looks me to a bit strange as all virtual channels interrupts
> line actually are the same. And we request that same irq line
> repeatedly here with the same irq handler.

Why not? Code is simple and performance should not be noticeable.

> > +       if (ret) {
> > +               dev_err(chan->mbox->dev,
> > +                       "Unable to acquire IRQ %d\n", cp->irq);
> > +               return ret;
> > +       }
> > +
> > +       imx_mu_rmw(priv, IMX_MU_xCR, IMX_MU_xCR_RIEn(cp->bidx), 0);
> > +
> > +       return 0;
> > +}
> > +
> > +static void imx_mu_shutdown(struct mbox_chan *chan)
> > +{
> > +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
> > +       struct imx_mu_con_priv *cp = chan->con_priv;
> > +
> > +       imx_mu_rmw(priv, IMX_MU_xCR, 0,
> > +                  IMX_MU_xCR_TIEn(cp->bidx) | IMX_MU_xCR_RIEn(cp->bidx));
> > +
> > +       free_irq(cp->irq, chan);
> > +}
> > +
> > +static const struct mbox_chan_ops imx_mu_ops = {
> > +       .send_data = imx_mu_send_data,
> > +       .startup = imx_mu_startup,
> > +       .shutdown = imx_mu_shutdown,
> > +       .last_tx_done = imx_mu_last_tx_done,
> 
> Do we really need this?
> Looking at the code, it seems .last_tx_done() is only called for polling mode.
> But what you set below is:
> priv->mbox.txdone_irq = true;
> 
> Or am i missed something?

no. I'll remove it for now.

> 
> > +};
> > +
> > +static int imx_mu_probe(struct platform_device *pdev)
> > +{
> > +       struct device *dev = &pdev->dev;
> > +       struct resource *iomem;
> > +       struct imx_mu_priv *priv;
> > +       const struct imx_mu_cfg *dcfg;
> > +       unsigned int i, chans;
> > +       int irq, ret;
> > +
> > +       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> > +       if (!priv)
> > +               return -ENOMEM;
> > +
> > +       dcfg = of_device_get_match_data(dev);
> > +       if (!dcfg)
> > +               return -EINVAL;
> > +
> > +       priv->dcfg = dcfg;
> > +       priv->dev = dev;
> > +
> > +       iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > +       priv->base = devm_ioremap_resource(&pdev->dev, iomem);
> > +       if (IS_ERR(priv->base))
> > +               return PTR_ERR(priv->base);
> > +
> > +       irq = platform_get_irq(pdev, 0);
> > +       if (irq <= 0)
> > +               return irq < 0 ? irq : -EINVAL;
> 
> Is it possible == 0?

no:
https://elixir.bootlin.com/linux/latest/source/drivers/base/platform.c#L86
or do I miss some thing?

> > +
> > +       priv->clk = devm_clk_get(dev, NULL);
> > +       if (IS_ERR(priv->clk)) {
> > +               if (PTR_ERR(priv->clk) == -ENOENT) {
> > +                       priv->clk = NULL;
> > +               } else {
> > +                       dev_err(dev, "Failed to get clock\n");
> 
> The line looks not be quite meaningful as it may be defer probe.

What is your suggestion?

> > +                       return PTR_ERR(priv->clk);
> > +               }
> > +       }
> > +
> > +       ret = clk_prepare_enable(priv->clk);
> > +       if (ret) {
> > +               dev_err(dev, "Failed to enable clock\n");
> > +               return ret;
> > +       }
> > +
> > +       chans = min(dcfg->chans, IMX_MU_MAX_CHANS);
> > +       /* Initialize channel identifiers */
> > +       for (i = 0; i < chans; i++) {
> > +               struct imx_mu_con_priv *cp = &priv->con_priv[i];
> > +
> > +               cp->bidx = 3 - i;
> > +               cp->idx = i;
> > +               cp->irq = irq;
> > +               priv->mbox_chans[i].con_priv = cp;
> > +       }
> > +
> > +       priv->mbox.dev = dev;
> > +       priv->mbox.ops = &imx_mu_ops;
> > +       priv->mbox.chans = priv->mbox_chans;
> > +       priv->mbox.num_chans = chans;
> > +       priv->mbox.txdone_irq = true;
> > +
> > +       platform_set_drvdata(pdev, priv);
> > +
> > +       if (priv->dcfg->init_hw)
> > +               priv->dcfg->init_hw(priv);
> > +
> > +       return mbox_controller_register(&priv->mbox);
> > +}
> > +
> > +static int imx_mu_remove(struct platform_device *pdev)
> > +{
> > +       struct imx_mu_priv *priv = platform_get_drvdata(pdev);
> > +
> > +       mbox_controller_unregister(&priv->mbox);
> > +       clk_disable_unprepare(priv->clk);
> > +
> > +       return 0;
> > +}
> > +
> > +
> > +static void imx_mu_init_imx7d_a(struct imx_mu_priv *priv)
> > +{
> > +       /* Set default config */
> > +       imx_mu_write(priv, 0, IMX_MU_xCR);
> > +}
> > +
> > +static const struct imx_mu_cfg imx_mu_cfg_imx7d_a = {
> > +       .chans = IMX_MU_MAX_CHANS,
> > +       .init_hw = imx_mu_init_imx7d_a,
> > +};
> > +
> > +static const struct imx_mu_cfg imx_mu_cfg_imx7d_b = {
> > +       .chans = IMX_MU_MAX_CHANS,
> > +};
> > +
> > +static const struct of_device_id imx_mu_dt_ids[] = {
> > +       { .compatible = "fsl,imx7s-mu-a", .data = &imx_mu_cfg_imx7d_a },
> > +       { .compatible = "fsl,imx7s-mu-b", .data = &imx_mu_cfg_imx7d_b },
> > +       { },
> > +};
> > +MODULE_DEVICE_TABLE(of, imx_mu_dt_ids);
> > +
> > +static struct platform_driver imx_mu_driver = {
> > +       .probe          = imx_mu_probe,
> > +       .remove         = imx_mu_remove,
> > +       .driver = {
> > +               .name   = "imx_mu",
> > +               .of_match_table = imx_mu_dt_ids,
> > +       },
> > +};
> > +module_platform_driver(imx_mu_driver);
> > +
> > +MODULE_AUTHOR("Oleksij Rempel <o.rempel@pengutronix.de>");
> > +MODULE_DESCRIPTION("Message Unit driver for i.MX7");
> 
> s/i.MX7/i.MX

ok

> Regards
> Dong Aisheng

thank you for review.

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180614/00022757/attachment.sig>

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v1 4/4] mailbox: Add support for i.MX7D messaging unit
  2018-06-13 12:24       ` Dong Aisheng
  (?)
@ 2018-06-15  6:23         ` Oleksij Rempel
  -1 siblings, 0 replies; 54+ messages in thread
From: Oleksij Rempel @ 2018-06-15  6:23 UTC (permalink / raw)
  To: Dong Aisheng
  Cc: Mark Rutland, devicetree, Peng Fan, Richard Zhu, linux-clk,
	Rob Herring, dl-linux-imx, Sascha Hauer, Fabio Estevam,
	Shawn Guo, Dong Aisheng,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE


[-- Attachment #1.1: Type: text/plain, Size: 14315 bytes --]

As promised, here are the sources.

I run Linux on Cortex M4 and A7 side. Here is my BSP:
git://git.pengutronix.de/ore/OSELAS.BSP-Pengutronix-DualKit
This BSP will create two images, for cortex m4, then make firmware image suitable
for rproc. Then it will create image for master system which will include rproc firmware.

and here is kernel source with all needed changes to run linux on both sides:
git://git.pengutronix.de/ore/linux

On Wed, Jun 13, 2018 at 08:24:09PM +0800, Dong Aisheng wrote:
> Copy linux-imx@nxp.com and more related guys to comment
> 
> On Wed, Jun 13, 2018 at 8:21 PM, Dong Aisheng <dongas86@gmail.com> wrote:
> > Hi Oleksij,
> >
> > On Fri, Jun 1, 2018 at 2:58 PM, Oleksij Rempel <o.rempel@pengutronix.de> wrote:
> >> The Mailbox controller is able to send messages (up to 4 32 bit words)
> >> between the endpoints.
> >
> > Could we really be able to send up to 4 42bit words with this driver?
> >
> > It looks to me the current Mailbox framework is more designed for share mem
> > transfer which does not fit i.MX MU well.
> >
> >>
> >> This driver was tested using the mailbox-test driver sending messages
> >> between the Cortex-A7 and the Cortex-M4.
> >
> > Would you please provide a guide on how to test it quickly?
> > I may want to give a test.
> >
> >>
> >> Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
> >> ---
> >>  drivers/mailbox/Kconfig       |   6 +
> >>  drivers/mailbox/Makefile      |   2 +
> >>  drivers/mailbox/imx-mailbox.c | 289 ++++++++++++++++++++++++++++++++++
> >>  3 files changed, 297 insertions(+)
> >>  create mode 100644 drivers/mailbox/imx-mailbox.c
> >>
> >> diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
> >> index a2bb27446dce..e1d2738a2e4c 100644
> >> --- a/drivers/mailbox/Kconfig
> >> +++ b/drivers/mailbox/Kconfig
> >> @@ -15,6 +15,12 @@ config ARM_MHU
> >>           The controller has 3 mailbox channels, the last of which can be
> >>           used in Secure mode only.
> >>
> >> +config IMX_MBOX
> >> +       tristate "iMX Mailbox"
> >> +       depends on SOC_IMX7D || COMPILE_TEST
> >> +       help
> >> +         Mailbox implementation for iMX7D Messaging Unit (MU).
> >> +
> >>  config PLATFORM_MHU
> >>         tristate "Platform MHU Mailbox"
> >>         depends on OF
> >> diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
> >> index cc23c3a43fcd..ba2fe1b6dd62 100644
> >> --- a/drivers/mailbox/Makefile
> >> +++ b/drivers/mailbox/Makefile
> >> @@ -7,6 +7,8 @@ obj-$(CONFIG_MAILBOX_TEST)      += mailbox-test.o
> >>
> >>  obj-$(CONFIG_ARM_MHU)  += arm_mhu.o
> >>
> >> +obj-$(CONFIG_IMX_MBOX) += imx-mailbox.o
> >> +
> >>  obj-$(CONFIG_PLATFORM_MHU)     += platform_mhu.o
> >>
> >>  obj-$(CONFIG_PL320_MBOX)       += pl320-ipc.o
> >> diff --git a/drivers/mailbox/imx-mailbox.c b/drivers/mailbox/imx-mailbox.c
> >> new file mode 100644
> >> index 000000000000..2bc9f11393b1
> >> --- /dev/null
> >> +++ b/drivers/mailbox/imx-mailbox.c
> >> @@ -0,0 +1,289 @@
> >> +// SPDX-License-Identifier: GPL-2.0
> >> +/*
> >> + * Copyright (c) 2018 Pengutronix, Oleksij Rempel <o.rempel@pengutronix.de>
> >> + */
> >> +
> >> +#include <linux/clk.h>
> >> +#include <linux/interrupt.h>
> >> +#include <linux/io.h>
> >> +#include <linux/kernel.h>
> >> +#include <linux/mailbox_controller.h>
> >> +#include <linux/module.h>
> >> +#include <linux/of_device.h>
> >> +
> >> +/* Transmit Register */
> >> +#define IMX_MU_xTRn(x)         (0x00 + 4 * (x))
> >> +/* Receive Register */
> >> +#define IMX_MU_xRRn(x)         (0x10 + 4 * (x))
> >> +/* Status Register */
> >> +#define IMX_MU_xSR             0x20
> >> +#define IMX_MU_xSR_TEn(x)      BIT(20 + (x))
> >> +#define IMX_MU_xSR_RFn(x)      BIT(24 + (x))
> >> +#define IMX_MU_xSR_BRDIP       BIT(9)
> >> +
> >> +/* Control Register */
> >> +#define IMX_MU_xCR             0x24
> >> +/* Transmit Interrupt Enable */
> >> +#define IMX_MU_xCR_TIEn(x)     BIT(20 + (x))
> >> +/* Receive Interrupt Enable */
> >> +#define IMX_MU_xCR_RIEn(x)     BIT(24 + (x))
> >> +
> >> +#define IMX_MU_MAX_CHANS       4u
> >> +
> >> +struct imx_mu_priv;
> >> +
> >> +struct imx_mu_cfg {
> >> +       unsigned int            chans;
> >> +       void (*init_hw)(struct imx_mu_priv *priv);
> >> +};
> >> +
> >> +struct imx_mu_con_priv {
> >> +       int                     irq;
> >> +       unsigned int            bidx;
> >> +       unsigned int            idx;
> >> +};
> >> +
> >> +struct imx_mu_priv {
> >> +       struct device           *dev;
> >> +       const struct imx_mu_cfg *dcfg;
> >> +       void __iomem            *base;
> >> +
> >> +       struct mbox_controller  mbox;
> >> +       struct mbox_chan        mbox_chans[IMX_MU_MAX_CHANS];
> >> +
> >> +       struct imx_mu_con_priv  con_priv[IMX_MU_MAX_CHANS];
> >> +       struct clk              *clk;
> >> +};
> >> +
> >> +static struct imx_mu_priv *to_imx_mu_priv(struct mbox_controller *mbox)
> >> +{
> >> +       return container_of(mbox, struct imx_mu_priv, mbox);
> >> +}
> >> +
> >> +static void imx_mu_write(struct imx_mu_priv *priv, u32 val, u32 offs)
> >> +{
> >> +       iowrite32(val, priv->base + offs);
> >> +}
> >> +
> >> +static u32 imx_mu_read(struct imx_mu_priv *priv, u32 offs)
> >> +{
> >> +       return ioread32(priv->base + offs);
> >> +}
> >> +
> >> +static u32 imx_mu_rmw(struct imx_mu_priv *priv, u32 offs, u32 set, u32 clr)
> >> +{
> >> +       u32 val;
> >> +
> >> +       val = imx_mu_read(priv, offs);
> >> +       val &= ~clr;
> >> +       val |= set;
> >> +       imx_mu_write(priv, val, offs);
> >> +
> >> +       return val;
> >> +}
> >> +
> >> +static irqreturn_t imx_mu_isr(int irq, void *p)
> >> +{
> >> +       struct mbox_chan *chan = p;
> >> +       struct imx_mu_con_priv *cp = chan->con_priv;
> >> +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
> >
> > Please do in reversed order from long to short
> >
> >> +
> >> +       u32 val, dat;
> >> +
> >> +       val = imx_mu_read(priv, IMX_MU_xSR);
> >> +       val &= IMX_MU_xSR_TEn(cp->bidx) | IMX_MU_xSR_RFn(cp->bidx);
> >> +       if (!val)
> >> +               return IRQ_NONE;
> >> +
> >> +       if (val & IMX_MU_xSR_TEn(cp->bidx)) {
> >> +               imx_mu_rmw(priv, IMX_MU_xCR, 0, IMX_MU_xCR_TIEn(cp->bidx));
> >> +               mbox_chan_txdone(chan, 0);
> >> +       }
> >> +
> >> +       if (val & IMX_MU_xSR_RFn(cp->bidx)) {
> >> +               dat = imx_mu_read(priv, IMX_MU_xRRn(cp->idx));
> >> +               mbox_chan_received_data(chan, (void *)&dat);
> >> +       }
> >> +
> >> +       return IRQ_HANDLED;
> >> +}
> >> +
> >> +static bool imx_mu_last_tx_done(struct mbox_chan *chan)
> >> +{
> >> +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
> >> +       struct imx_mu_con_priv *cp = chan->con_priv;
> >> +       u32 val;
> >> +
> >> +       val = imx_mu_read(priv, IMX_MU_xSR);
> >> +       /* test if transmit register is empty */
> >> +       return (!(val & IMX_MU_xSR_TEn(cp->bidx)));
> >> +}
> >> +
> >> +static int imx_mu_send_data(struct mbox_chan *chan, void *data)
> >> +{
> >> +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
> >> +       struct imx_mu_con_priv *cp = chan->con_priv;
> >> +       u32 *arg = data;
> >> +
> >> +       if (imx_mu_last_tx_done(chan))
> >
> > return true for tx_done?
> > Or maybe better imx_mu_is_busy?
> >
> >> +               return -EBUSY;
> >> +
> >> +       imx_mu_write(priv, *arg, IMX_MU_xTRn(cp->idx));
> >> +       imx_mu_rmw(priv, IMX_MU_xCR, IMX_MU_xSR_TEn(cp->bidx), 0);
> >> +
> >> +       return 0;
> >> +}
> >> +
> >> +static int imx_mu_startup(struct mbox_chan *chan)
> >> +{
> >> +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
> >> +       struct imx_mu_con_priv *cp = chan->con_priv;
> >> +       int ret;
> >> +
> >> +       ret = request_irq(cp->irq, imx_mu_isr,
> >> +                         IRQF_SHARED, "imx_mu_chan", chan);
> >
> > This looks me to a bit strange as all virtual channels interrupts
> > line actually are the same. And we request that same irq line
> > repeatedly here with the same irq handler.
> >
> >> +       if (ret) {
> >> +               dev_err(chan->mbox->dev,
> >> +                       "Unable to acquire IRQ %d\n", cp->irq);
> >> +               return ret;
> >> +       }
> >> +
> >> +       imx_mu_rmw(priv, IMX_MU_xCR, IMX_MU_xCR_RIEn(cp->bidx), 0);
> >> +
> >> +       return 0;
> >> +}
> >> +
> >> +static void imx_mu_shutdown(struct mbox_chan *chan)
> >> +{
> >> +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
> >> +       struct imx_mu_con_priv *cp = chan->con_priv;
> >> +
> >> +       imx_mu_rmw(priv, IMX_MU_xCR, 0,
> >> +                  IMX_MU_xCR_TIEn(cp->bidx) | IMX_MU_xCR_RIEn(cp->bidx));
> >> +
> >> +       free_irq(cp->irq, chan);
> >> +}
> >> +
> >> +static const struct mbox_chan_ops imx_mu_ops = {
> >> +       .send_data = imx_mu_send_data,
> >> +       .startup = imx_mu_startup,
> >> +       .shutdown = imx_mu_shutdown,
> >> +       .last_tx_done = imx_mu_last_tx_done,
> >
> > Do we really need this?
> > Looking at the code, it seems .last_tx_done() is only called for polling mode.
> > But what you set below is:
> > priv->mbox.txdone_irq = true;
> >
> > Or am i missed something?
> >
> >> +};
> >> +
> >> +static int imx_mu_probe(struct platform_device *pdev)
> >> +{
> >> +       struct device *dev = &pdev->dev;
> >> +       struct resource *iomem;
> >> +       struct imx_mu_priv *priv;
> >> +       const struct imx_mu_cfg *dcfg;
> >> +       unsigned int i, chans;
> >> +       int irq, ret;
> >> +
> >> +       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> >> +       if (!priv)
> >> +               return -ENOMEM;
> >> +
> >> +       dcfg = of_device_get_match_data(dev);
> >> +       if (!dcfg)
> >> +               return -EINVAL;
> >> +
> >> +       priv->dcfg = dcfg;
> >> +       priv->dev = dev;
> >> +
> >> +       iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> >> +       priv->base = devm_ioremap_resource(&pdev->dev, iomem);
> >> +       if (IS_ERR(priv->base))
> >> +               return PTR_ERR(priv->base);
> >> +
> >> +       irq = platform_get_irq(pdev, 0);
> >> +       if (irq <= 0)
> >> +               return irq < 0 ? irq : -EINVAL;
> >
> > Is it possible == 0?
> >
> >> +
> >> +       priv->clk = devm_clk_get(dev, NULL);
> >> +       if (IS_ERR(priv->clk)) {
> >> +               if (PTR_ERR(priv->clk) == -ENOENT) {
> >> +                       priv->clk = NULL;
> >> +               } else {
> >> +                       dev_err(dev, "Failed to get clock\n");
> >
> > The line looks not be quite meaningful as it may be defer probe.
> >
> >> +                       return PTR_ERR(priv->clk);
> >> +               }
> >> +       }
> >> +
> >> +       ret = clk_prepare_enable(priv->clk);
> >> +       if (ret) {
> >> +               dev_err(dev, "Failed to enable clock\n");
> >> +               return ret;
> >> +       }
> >> +
> >> +       chans = min(dcfg->chans, IMX_MU_MAX_CHANS);
> >> +       /* Initialize channel identifiers */
> >> +       for (i = 0; i < chans; i++) {
> >> +               struct imx_mu_con_priv *cp = &priv->con_priv[i];
> >> +
> >> +               cp->bidx = 3 - i;
> >> +               cp->idx = i;
> >> +               cp->irq = irq;
> >> +               priv->mbox_chans[i].con_priv = cp;
> >> +       }
> >> +
> >> +       priv->mbox.dev = dev;
> >> +       priv->mbox.ops = &imx_mu_ops;
> >> +       priv->mbox.chans = priv->mbox_chans;
> >> +       priv->mbox.num_chans = chans;
> >> +       priv->mbox.txdone_irq = true;
> >> +
> >> +       platform_set_drvdata(pdev, priv);
> >> +
> >> +       if (priv->dcfg->init_hw)
> >> +               priv->dcfg->init_hw(priv);
> >> +
> >> +       return mbox_controller_register(&priv->mbox);
> >> +}
> >> +
> >> +static int imx_mu_remove(struct platform_device *pdev)
> >> +{
> >> +       struct imx_mu_priv *priv = platform_get_drvdata(pdev);
> >> +
> >> +       mbox_controller_unregister(&priv->mbox);
> >> +       clk_disable_unprepare(priv->clk);
> >> +
> >> +       return 0;
> >> +}
> >> +
> >> +
> >> +static void imx_mu_init_imx7d_a(struct imx_mu_priv *priv)
> >> +{
> >> +       /* Set default config */
> >> +       imx_mu_write(priv, 0, IMX_MU_xCR);
> >> +}
> >> +
> >> +static const struct imx_mu_cfg imx_mu_cfg_imx7d_a = {
> >> +       .chans = IMX_MU_MAX_CHANS,
> >> +       .init_hw = imx_mu_init_imx7d_a,
> >> +};
> >> +
> >> +static const struct imx_mu_cfg imx_mu_cfg_imx7d_b = {
> >> +       .chans = IMX_MU_MAX_CHANS,
> >> +};
> >> +
> >> +static const struct of_device_id imx_mu_dt_ids[] = {
> >> +       { .compatible = "fsl,imx7s-mu-a", .data = &imx_mu_cfg_imx7d_a },
> >> +       { .compatible = "fsl,imx7s-mu-b", .data = &imx_mu_cfg_imx7d_b },
> >> +       { },
> >> +};
> >> +MODULE_DEVICE_TABLE(of, imx_mu_dt_ids);
> >> +
> >> +static struct platform_driver imx_mu_driver = {
> >> +       .probe          = imx_mu_probe,
> >> +       .remove         = imx_mu_remove,
> >> +       .driver = {
> >> +               .name   = "imx_mu",
> >> +               .of_match_table = imx_mu_dt_ids,
> >> +       },
> >> +};
> >> +module_platform_driver(imx_mu_driver);
> >> +
> >> +MODULE_AUTHOR("Oleksij Rempel <o.rempel@pengutronix.de>");
> >> +MODULE_DESCRIPTION("Message Unit driver for i.MX7");
> >
> > s/i.MX7/i.MX
> >
> > Regards
> > Dong Aisheng
> >
> >> +MODULE_LICENSE("GPL v2");
> >> --
> >> 2.17.1
> >>
> >> --
> >> To unsubscribe from this list: send the line "unsubscribe linux-clk" in
> >> the body of a message to majordomo@vger.kernel.org
> >> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
> 

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

[-- Attachment #2: Type: text/plain, Size: 176 bytes --]

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 54+ messages in thread

* Re: [PATCH v1 4/4] mailbox: Add support for i.MX7D messaging unit
@ 2018-06-15  6:23         ` Oleksij Rempel
  0 siblings, 0 replies; 54+ messages in thread
From: Oleksij Rempel @ 2018-06-15  6:23 UTC (permalink / raw)
  To: Dong Aisheng
  Cc: Mark Rutland, devicetree, Peng Fan, Richard Zhu, Rob Herring,
	dl-linux-imx, Sascha Hauer, Dong Aisheng, Fabio Estevam,
	Shawn Guo, linux-clk,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE

[-- Attachment #1: Type: text/plain, Size: 14315 bytes --]

As promised, here are the sources.

I run Linux on Cortex M4 and A7 side. Here is my BSP:
git://git.pengutronix.de/ore/OSELAS.BSP-Pengutronix-DualKit
This BSP will create two images, for cortex m4, then make firmware image suitable
for rproc. Then it will create image for master system which will include rproc firmware.

and here is kernel source with all needed changes to run linux on both sides:
git://git.pengutronix.de/ore/linux

On Wed, Jun 13, 2018 at 08:24:09PM +0800, Dong Aisheng wrote:
> Copy linux-imx@nxp.com and more related guys to comment
> 
> On Wed, Jun 13, 2018 at 8:21 PM, Dong Aisheng <dongas86@gmail.com> wrote:
> > Hi Oleksij,
> >
> > On Fri, Jun 1, 2018 at 2:58 PM, Oleksij Rempel <o.rempel@pengutronix.de> wrote:
> >> The Mailbox controller is able to send messages (up to 4 32 bit words)
> >> between the endpoints.
> >
> > Could we really be able to send up to 4 42bit words with this driver?
> >
> > It looks to me the current Mailbox framework is more designed for share mem
> > transfer which does not fit i.MX MU well.
> >
> >>
> >> This driver was tested using the mailbox-test driver sending messages
> >> between the Cortex-A7 and the Cortex-M4.
> >
> > Would you please provide a guide on how to test it quickly?
> > I may want to give a test.
> >
> >>
> >> Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
> >> ---
> >>  drivers/mailbox/Kconfig       |   6 +
> >>  drivers/mailbox/Makefile      |   2 +
> >>  drivers/mailbox/imx-mailbox.c | 289 ++++++++++++++++++++++++++++++++++
> >>  3 files changed, 297 insertions(+)
> >>  create mode 100644 drivers/mailbox/imx-mailbox.c
> >>
> >> diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
> >> index a2bb27446dce..e1d2738a2e4c 100644
> >> --- a/drivers/mailbox/Kconfig
> >> +++ b/drivers/mailbox/Kconfig
> >> @@ -15,6 +15,12 @@ config ARM_MHU
> >>           The controller has 3 mailbox channels, the last of which can be
> >>           used in Secure mode only.
> >>
> >> +config IMX_MBOX
> >> +       tristate "iMX Mailbox"
> >> +       depends on SOC_IMX7D || COMPILE_TEST
> >> +       help
> >> +         Mailbox implementation for iMX7D Messaging Unit (MU).
> >> +
> >>  config PLATFORM_MHU
> >>         tristate "Platform MHU Mailbox"
> >>         depends on OF
> >> diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
> >> index cc23c3a43fcd..ba2fe1b6dd62 100644
> >> --- a/drivers/mailbox/Makefile
> >> +++ b/drivers/mailbox/Makefile
> >> @@ -7,6 +7,8 @@ obj-$(CONFIG_MAILBOX_TEST)      += mailbox-test.o
> >>
> >>  obj-$(CONFIG_ARM_MHU)  += arm_mhu.o
> >>
> >> +obj-$(CONFIG_IMX_MBOX) += imx-mailbox.o
> >> +
> >>  obj-$(CONFIG_PLATFORM_MHU)     += platform_mhu.o
> >>
> >>  obj-$(CONFIG_PL320_MBOX)       += pl320-ipc.o
> >> diff --git a/drivers/mailbox/imx-mailbox.c b/drivers/mailbox/imx-mailbox.c
> >> new file mode 100644
> >> index 000000000000..2bc9f11393b1
> >> --- /dev/null
> >> +++ b/drivers/mailbox/imx-mailbox.c
> >> @@ -0,0 +1,289 @@
> >> +// SPDX-License-Identifier: GPL-2.0
> >> +/*
> >> + * Copyright (c) 2018 Pengutronix, Oleksij Rempel <o.rempel@pengutronix.de>
> >> + */
> >> +
> >> +#include <linux/clk.h>
> >> +#include <linux/interrupt.h>
> >> +#include <linux/io.h>
> >> +#include <linux/kernel.h>
> >> +#include <linux/mailbox_controller.h>
> >> +#include <linux/module.h>
> >> +#include <linux/of_device.h>
> >> +
> >> +/* Transmit Register */
> >> +#define IMX_MU_xTRn(x)         (0x00 + 4 * (x))
> >> +/* Receive Register */
> >> +#define IMX_MU_xRRn(x)         (0x10 + 4 * (x))
> >> +/* Status Register */
> >> +#define IMX_MU_xSR             0x20
> >> +#define IMX_MU_xSR_TEn(x)      BIT(20 + (x))
> >> +#define IMX_MU_xSR_RFn(x)      BIT(24 + (x))
> >> +#define IMX_MU_xSR_BRDIP       BIT(9)
> >> +
> >> +/* Control Register */
> >> +#define IMX_MU_xCR             0x24
> >> +/* Transmit Interrupt Enable */
> >> +#define IMX_MU_xCR_TIEn(x)     BIT(20 + (x))
> >> +/* Receive Interrupt Enable */
> >> +#define IMX_MU_xCR_RIEn(x)     BIT(24 + (x))
> >> +
> >> +#define IMX_MU_MAX_CHANS       4u
> >> +
> >> +struct imx_mu_priv;
> >> +
> >> +struct imx_mu_cfg {
> >> +       unsigned int            chans;
> >> +       void (*init_hw)(struct imx_mu_priv *priv);
> >> +};
> >> +
> >> +struct imx_mu_con_priv {
> >> +       int                     irq;
> >> +       unsigned int            bidx;
> >> +       unsigned int            idx;
> >> +};
> >> +
> >> +struct imx_mu_priv {
> >> +       struct device           *dev;
> >> +       const struct imx_mu_cfg *dcfg;
> >> +       void __iomem            *base;
> >> +
> >> +       struct mbox_controller  mbox;
> >> +       struct mbox_chan        mbox_chans[IMX_MU_MAX_CHANS];
> >> +
> >> +       struct imx_mu_con_priv  con_priv[IMX_MU_MAX_CHANS];
> >> +       struct clk              *clk;
> >> +};
> >> +
> >> +static struct imx_mu_priv *to_imx_mu_priv(struct mbox_controller *mbox)
> >> +{
> >> +       return container_of(mbox, struct imx_mu_priv, mbox);
> >> +}
> >> +
> >> +static void imx_mu_write(struct imx_mu_priv *priv, u32 val, u32 offs)
> >> +{
> >> +       iowrite32(val, priv->base + offs);
> >> +}
> >> +
> >> +static u32 imx_mu_read(struct imx_mu_priv *priv, u32 offs)
> >> +{
> >> +       return ioread32(priv->base + offs);
> >> +}
> >> +
> >> +static u32 imx_mu_rmw(struct imx_mu_priv *priv, u32 offs, u32 set, u32 clr)
> >> +{
> >> +       u32 val;
> >> +
> >> +       val = imx_mu_read(priv, offs);
> >> +       val &= ~clr;
> >> +       val |= set;
> >> +       imx_mu_write(priv, val, offs);
> >> +
> >> +       return val;
> >> +}
> >> +
> >> +static irqreturn_t imx_mu_isr(int irq, void *p)
> >> +{
> >> +       struct mbox_chan *chan = p;
> >> +       struct imx_mu_con_priv *cp = chan->con_priv;
> >> +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
> >
> > Please do in reversed order from long to short
> >
> >> +
> >> +       u32 val, dat;
> >> +
> >> +       val = imx_mu_read(priv, IMX_MU_xSR);
> >> +       val &= IMX_MU_xSR_TEn(cp->bidx) | IMX_MU_xSR_RFn(cp->bidx);
> >> +       if (!val)
> >> +               return IRQ_NONE;
> >> +
> >> +       if (val & IMX_MU_xSR_TEn(cp->bidx)) {
> >> +               imx_mu_rmw(priv, IMX_MU_xCR, 0, IMX_MU_xCR_TIEn(cp->bidx));
> >> +               mbox_chan_txdone(chan, 0);
> >> +       }
> >> +
> >> +       if (val & IMX_MU_xSR_RFn(cp->bidx)) {
> >> +               dat = imx_mu_read(priv, IMX_MU_xRRn(cp->idx));
> >> +               mbox_chan_received_data(chan, (void *)&dat);
> >> +       }
> >> +
> >> +       return IRQ_HANDLED;
> >> +}
> >> +
> >> +static bool imx_mu_last_tx_done(struct mbox_chan *chan)
> >> +{
> >> +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
> >> +       struct imx_mu_con_priv *cp = chan->con_priv;
> >> +       u32 val;
> >> +
> >> +       val = imx_mu_read(priv, IMX_MU_xSR);
> >> +       /* test if transmit register is empty */
> >> +       return (!(val & IMX_MU_xSR_TEn(cp->bidx)));
> >> +}
> >> +
> >> +static int imx_mu_send_data(struct mbox_chan *chan, void *data)
> >> +{
> >> +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
> >> +       struct imx_mu_con_priv *cp = chan->con_priv;
> >> +       u32 *arg = data;
> >> +
> >> +       if (imx_mu_last_tx_done(chan))
> >
> > return true for tx_done?
> > Or maybe better imx_mu_is_busy?
> >
> >> +               return -EBUSY;
> >> +
> >> +       imx_mu_write(priv, *arg, IMX_MU_xTRn(cp->idx));
> >> +       imx_mu_rmw(priv, IMX_MU_xCR, IMX_MU_xSR_TEn(cp->bidx), 0);
> >> +
> >> +       return 0;
> >> +}
> >> +
> >> +static int imx_mu_startup(struct mbox_chan *chan)
> >> +{
> >> +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
> >> +       struct imx_mu_con_priv *cp = chan->con_priv;
> >> +       int ret;
> >> +
> >> +       ret = request_irq(cp->irq, imx_mu_isr,
> >> +                         IRQF_SHARED, "imx_mu_chan", chan);
> >
> > This looks me to a bit strange as all virtual channels interrupts
> > line actually are the same. And we request that same irq line
> > repeatedly here with the same irq handler.
> >
> >> +       if (ret) {
> >> +               dev_err(chan->mbox->dev,
> >> +                       "Unable to acquire IRQ %d\n", cp->irq);
> >> +               return ret;
> >> +       }
> >> +
> >> +       imx_mu_rmw(priv, IMX_MU_xCR, IMX_MU_xCR_RIEn(cp->bidx), 0);
> >> +
> >> +       return 0;
> >> +}
> >> +
> >> +static void imx_mu_shutdown(struct mbox_chan *chan)
> >> +{
> >> +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
> >> +       struct imx_mu_con_priv *cp = chan->con_priv;
> >> +
> >> +       imx_mu_rmw(priv, IMX_MU_xCR, 0,
> >> +                  IMX_MU_xCR_TIEn(cp->bidx) | IMX_MU_xCR_RIEn(cp->bidx));
> >> +
> >> +       free_irq(cp->irq, chan);
> >> +}
> >> +
> >> +static const struct mbox_chan_ops imx_mu_ops = {
> >> +       .send_data = imx_mu_send_data,
> >> +       .startup = imx_mu_startup,
> >> +       .shutdown = imx_mu_shutdown,
> >> +       .last_tx_done = imx_mu_last_tx_done,
> >
> > Do we really need this?
> > Looking at the code, it seems .last_tx_done() is only called for polling mode.
> > But what you set below is:
> > priv->mbox.txdone_irq = true;
> >
> > Or am i missed something?
> >
> >> +};
> >> +
> >> +static int imx_mu_probe(struct platform_device *pdev)
> >> +{
> >> +       struct device *dev = &pdev->dev;
> >> +       struct resource *iomem;
> >> +       struct imx_mu_priv *priv;
> >> +       const struct imx_mu_cfg *dcfg;
> >> +       unsigned int i, chans;
> >> +       int irq, ret;
> >> +
> >> +       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> >> +       if (!priv)
> >> +               return -ENOMEM;
> >> +
> >> +       dcfg = of_device_get_match_data(dev);
> >> +       if (!dcfg)
> >> +               return -EINVAL;
> >> +
> >> +       priv->dcfg = dcfg;
> >> +       priv->dev = dev;
> >> +
> >> +       iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> >> +       priv->base = devm_ioremap_resource(&pdev->dev, iomem);
> >> +       if (IS_ERR(priv->base))
> >> +               return PTR_ERR(priv->base);
> >> +
> >> +       irq = platform_get_irq(pdev, 0);
> >> +       if (irq <= 0)
> >> +               return irq < 0 ? irq : -EINVAL;
> >
> > Is it possible == 0?
> >
> >> +
> >> +       priv->clk = devm_clk_get(dev, NULL);
> >> +       if (IS_ERR(priv->clk)) {
> >> +               if (PTR_ERR(priv->clk) == -ENOENT) {
> >> +                       priv->clk = NULL;
> >> +               } else {
> >> +                       dev_err(dev, "Failed to get clock\n");
> >
> > The line looks not be quite meaningful as it may be defer probe.
> >
> >> +                       return PTR_ERR(priv->clk);
> >> +               }
> >> +       }
> >> +
> >> +       ret = clk_prepare_enable(priv->clk);
> >> +       if (ret) {
> >> +               dev_err(dev, "Failed to enable clock\n");
> >> +               return ret;
> >> +       }
> >> +
> >> +       chans = min(dcfg->chans, IMX_MU_MAX_CHANS);
> >> +       /* Initialize channel identifiers */
> >> +       for (i = 0; i < chans; i++) {
> >> +               struct imx_mu_con_priv *cp = &priv->con_priv[i];
> >> +
> >> +               cp->bidx = 3 - i;
> >> +               cp->idx = i;
> >> +               cp->irq = irq;
> >> +               priv->mbox_chans[i].con_priv = cp;
> >> +       }
> >> +
> >> +       priv->mbox.dev = dev;
> >> +       priv->mbox.ops = &imx_mu_ops;
> >> +       priv->mbox.chans = priv->mbox_chans;
> >> +       priv->mbox.num_chans = chans;
> >> +       priv->mbox.txdone_irq = true;
> >> +
> >> +       platform_set_drvdata(pdev, priv);
> >> +
> >> +       if (priv->dcfg->init_hw)
> >> +               priv->dcfg->init_hw(priv);
> >> +
> >> +       return mbox_controller_register(&priv->mbox);
> >> +}
> >> +
> >> +static int imx_mu_remove(struct platform_device *pdev)
> >> +{
> >> +       struct imx_mu_priv *priv = platform_get_drvdata(pdev);
> >> +
> >> +       mbox_controller_unregister(&priv->mbox);
> >> +       clk_disable_unprepare(priv->clk);
> >> +
> >> +       return 0;
> >> +}
> >> +
> >> +
> >> +static void imx_mu_init_imx7d_a(struct imx_mu_priv *priv)
> >> +{
> >> +       /* Set default config */
> >> +       imx_mu_write(priv, 0, IMX_MU_xCR);
> >> +}
> >> +
> >> +static const struct imx_mu_cfg imx_mu_cfg_imx7d_a = {
> >> +       .chans = IMX_MU_MAX_CHANS,
> >> +       .init_hw = imx_mu_init_imx7d_a,
> >> +};
> >> +
> >> +static const struct imx_mu_cfg imx_mu_cfg_imx7d_b = {
> >> +       .chans = IMX_MU_MAX_CHANS,
> >> +};
> >> +
> >> +static const struct of_device_id imx_mu_dt_ids[] = {
> >> +       { .compatible = "fsl,imx7s-mu-a", .data = &imx_mu_cfg_imx7d_a },
> >> +       { .compatible = "fsl,imx7s-mu-b", .data = &imx_mu_cfg_imx7d_b },
> >> +       { },
> >> +};
> >> +MODULE_DEVICE_TABLE(of, imx_mu_dt_ids);
> >> +
> >> +static struct platform_driver imx_mu_driver = {
> >> +       .probe          = imx_mu_probe,
> >> +       .remove         = imx_mu_remove,
> >> +       .driver = {
> >> +               .name   = "imx_mu",
> >> +               .of_match_table = imx_mu_dt_ids,
> >> +       },
> >> +};
> >> +module_platform_driver(imx_mu_driver);
> >> +
> >> +MODULE_AUTHOR("Oleksij Rempel <o.rempel@pengutronix.de>");
> >> +MODULE_DESCRIPTION("Message Unit driver for i.MX7");
> >
> > s/i.MX7/i.MX
> >
> > Regards
> > Dong Aisheng
> >
> >> +MODULE_LICENSE("GPL v2");
> >> --
> >> 2.17.1
> >>
> >> --
> >> To unsubscribe from this list: send the line "unsubscribe linux-clk" in
> >> the body of a message to majordomo@vger.kernel.org
> >> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
> 

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 54+ messages in thread

* [PATCH v1 4/4] mailbox: Add support for i.MX7D messaging unit
@ 2018-06-15  6:23         ` Oleksij Rempel
  0 siblings, 0 replies; 54+ messages in thread
From: Oleksij Rempel @ 2018-06-15  6:23 UTC (permalink / raw)
  To: linux-arm-kernel

As promised, here are the sources.

I run Linux on Cortex M4 and A7 side. Here is my BSP:
git://git.pengutronix.de/ore/OSELAS.BSP-Pengutronix-DualKit
This BSP will create two images, for cortex m4, then make firmware image suitable
for rproc. Then it will create image for master system which will include rproc firmware.

and here is kernel source with all needed changes to run linux on both sides:
git://git.pengutronix.de/ore/linux

On Wed, Jun 13, 2018 at 08:24:09PM +0800, Dong Aisheng wrote:
> Copy linux-imx at nxp.com and more related guys to comment
> 
> On Wed, Jun 13, 2018 at 8:21 PM, Dong Aisheng <dongas86@gmail.com> wrote:
> > Hi Oleksij,
> >
> > On Fri, Jun 1, 2018 at 2:58 PM, Oleksij Rempel <o.rempel@pengutronix.de> wrote:
> >> The Mailbox controller is able to send messages (up to 4 32 bit words)
> >> between the endpoints.
> >
> > Could we really be able to send up to 4 42bit words with this driver?
> >
> > It looks to me the current Mailbox framework is more designed for share mem
> > transfer which does not fit i.MX MU well.
> >
> >>
> >> This driver was tested using the mailbox-test driver sending messages
> >> between the Cortex-A7 and the Cortex-M4.
> >
> > Would you please provide a guide on how to test it quickly?
> > I may want to give a test.
> >
> >>
> >> Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
> >> ---
> >>  drivers/mailbox/Kconfig       |   6 +
> >>  drivers/mailbox/Makefile      |   2 +
> >>  drivers/mailbox/imx-mailbox.c | 289 ++++++++++++++++++++++++++++++++++
> >>  3 files changed, 297 insertions(+)
> >>  create mode 100644 drivers/mailbox/imx-mailbox.c
> >>
> >> diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
> >> index a2bb27446dce..e1d2738a2e4c 100644
> >> --- a/drivers/mailbox/Kconfig
> >> +++ b/drivers/mailbox/Kconfig
> >> @@ -15,6 +15,12 @@ config ARM_MHU
> >>           The controller has 3 mailbox channels, the last of which can be
> >>           used in Secure mode only.
> >>
> >> +config IMX_MBOX
> >> +       tristate "iMX Mailbox"
> >> +       depends on SOC_IMX7D || COMPILE_TEST
> >> +       help
> >> +         Mailbox implementation for iMX7D Messaging Unit (MU).
> >> +
> >>  config PLATFORM_MHU
> >>         tristate "Platform MHU Mailbox"
> >>         depends on OF
> >> diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
> >> index cc23c3a43fcd..ba2fe1b6dd62 100644
> >> --- a/drivers/mailbox/Makefile
> >> +++ b/drivers/mailbox/Makefile
> >> @@ -7,6 +7,8 @@ obj-$(CONFIG_MAILBOX_TEST)      += mailbox-test.o
> >>
> >>  obj-$(CONFIG_ARM_MHU)  += arm_mhu.o
> >>
> >> +obj-$(CONFIG_IMX_MBOX) += imx-mailbox.o
> >> +
> >>  obj-$(CONFIG_PLATFORM_MHU)     += platform_mhu.o
> >>
> >>  obj-$(CONFIG_PL320_MBOX)       += pl320-ipc.o
> >> diff --git a/drivers/mailbox/imx-mailbox.c b/drivers/mailbox/imx-mailbox.c
> >> new file mode 100644
> >> index 000000000000..2bc9f11393b1
> >> --- /dev/null
> >> +++ b/drivers/mailbox/imx-mailbox.c
> >> @@ -0,0 +1,289 @@
> >> +// SPDX-License-Identifier: GPL-2.0
> >> +/*
> >> + * Copyright (c) 2018 Pengutronix, Oleksij Rempel <o.rempel@pengutronix.de>
> >> + */
> >> +
> >> +#include <linux/clk.h>
> >> +#include <linux/interrupt.h>
> >> +#include <linux/io.h>
> >> +#include <linux/kernel.h>
> >> +#include <linux/mailbox_controller.h>
> >> +#include <linux/module.h>
> >> +#include <linux/of_device.h>
> >> +
> >> +/* Transmit Register */
> >> +#define IMX_MU_xTRn(x)         (0x00 + 4 * (x))
> >> +/* Receive Register */
> >> +#define IMX_MU_xRRn(x)         (0x10 + 4 * (x))
> >> +/* Status Register */
> >> +#define IMX_MU_xSR             0x20
> >> +#define IMX_MU_xSR_TEn(x)      BIT(20 + (x))
> >> +#define IMX_MU_xSR_RFn(x)      BIT(24 + (x))
> >> +#define IMX_MU_xSR_BRDIP       BIT(9)
> >> +
> >> +/* Control Register */
> >> +#define IMX_MU_xCR             0x24
> >> +/* Transmit Interrupt Enable */
> >> +#define IMX_MU_xCR_TIEn(x)     BIT(20 + (x))
> >> +/* Receive Interrupt Enable */
> >> +#define IMX_MU_xCR_RIEn(x)     BIT(24 + (x))
> >> +
> >> +#define IMX_MU_MAX_CHANS       4u
> >> +
> >> +struct imx_mu_priv;
> >> +
> >> +struct imx_mu_cfg {
> >> +       unsigned int            chans;
> >> +       void (*init_hw)(struct imx_mu_priv *priv);
> >> +};
> >> +
> >> +struct imx_mu_con_priv {
> >> +       int                     irq;
> >> +       unsigned int            bidx;
> >> +       unsigned int            idx;
> >> +};
> >> +
> >> +struct imx_mu_priv {
> >> +       struct device           *dev;
> >> +       const struct imx_mu_cfg *dcfg;
> >> +       void __iomem            *base;
> >> +
> >> +       struct mbox_controller  mbox;
> >> +       struct mbox_chan        mbox_chans[IMX_MU_MAX_CHANS];
> >> +
> >> +       struct imx_mu_con_priv  con_priv[IMX_MU_MAX_CHANS];
> >> +       struct clk              *clk;
> >> +};
> >> +
> >> +static struct imx_mu_priv *to_imx_mu_priv(struct mbox_controller *mbox)
> >> +{
> >> +       return container_of(mbox, struct imx_mu_priv, mbox);
> >> +}
> >> +
> >> +static void imx_mu_write(struct imx_mu_priv *priv, u32 val, u32 offs)
> >> +{
> >> +       iowrite32(val, priv->base + offs);
> >> +}
> >> +
> >> +static u32 imx_mu_read(struct imx_mu_priv *priv, u32 offs)
> >> +{
> >> +       return ioread32(priv->base + offs);
> >> +}
> >> +
> >> +static u32 imx_mu_rmw(struct imx_mu_priv *priv, u32 offs, u32 set, u32 clr)
> >> +{
> >> +       u32 val;
> >> +
> >> +       val = imx_mu_read(priv, offs);
> >> +       val &= ~clr;
> >> +       val |= set;
> >> +       imx_mu_write(priv, val, offs);
> >> +
> >> +       return val;
> >> +}
> >> +
> >> +static irqreturn_t imx_mu_isr(int irq, void *p)
> >> +{
> >> +       struct mbox_chan *chan = p;
> >> +       struct imx_mu_con_priv *cp = chan->con_priv;
> >> +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
> >
> > Please do in reversed order from long to short
> >
> >> +
> >> +       u32 val, dat;
> >> +
> >> +       val = imx_mu_read(priv, IMX_MU_xSR);
> >> +       val &= IMX_MU_xSR_TEn(cp->bidx) | IMX_MU_xSR_RFn(cp->bidx);
> >> +       if (!val)
> >> +               return IRQ_NONE;
> >> +
> >> +       if (val & IMX_MU_xSR_TEn(cp->bidx)) {
> >> +               imx_mu_rmw(priv, IMX_MU_xCR, 0, IMX_MU_xCR_TIEn(cp->bidx));
> >> +               mbox_chan_txdone(chan, 0);
> >> +       }
> >> +
> >> +       if (val & IMX_MU_xSR_RFn(cp->bidx)) {
> >> +               dat = imx_mu_read(priv, IMX_MU_xRRn(cp->idx));
> >> +               mbox_chan_received_data(chan, (void *)&dat);
> >> +       }
> >> +
> >> +       return IRQ_HANDLED;
> >> +}
> >> +
> >> +static bool imx_mu_last_tx_done(struct mbox_chan *chan)
> >> +{
> >> +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
> >> +       struct imx_mu_con_priv *cp = chan->con_priv;
> >> +       u32 val;
> >> +
> >> +       val = imx_mu_read(priv, IMX_MU_xSR);
> >> +       /* test if transmit register is empty */
> >> +       return (!(val & IMX_MU_xSR_TEn(cp->bidx)));
> >> +}
> >> +
> >> +static int imx_mu_send_data(struct mbox_chan *chan, void *data)
> >> +{
> >> +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
> >> +       struct imx_mu_con_priv *cp = chan->con_priv;
> >> +       u32 *arg = data;
> >> +
> >> +       if (imx_mu_last_tx_done(chan))
> >
> > return true for tx_done?
> > Or maybe better imx_mu_is_busy?
> >
> >> +               return -EBUSY;
> >> +
> >> +       imx_mu_write(priv, *arg, IMX_MU_xTRn(cp->idx));
> >> +       imx_mu_rmw(priv, IMX_MU_xCR, IMX_MU_xSR_TEn(cp->bidx), 0);
> >> +
> >> +       return 0;
> >> +}
> >> +
> >> +static int imx_mu_startup(struct mbox_chan *chan)
> >> +{
> >> +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
> >> +       struct imx_mu_con_priv *cp = chan->con_priv;
> >> +       int ret;
> >> +
> >> +       ret = request_irq(cp->irq, imx_mu_isr,
> >> +                         IRQF_SHARED, "imx_mu_chan", chan);
> >
> > This looks me to a bit strange as all virtual channels interrupts
> > line actually are the same. And we request that same irq line
> > repeatedly here with the same irq handler.
> >
> >> +       if (ret) {
> >> +               dev_err(chan->mbox->dev,
> >> +                       "Unable to acquire IRQ %d\n", cp->irq);
> >> +               return ret;
> >> +       }
> >> +
> >> +       imx_mu_rmw(priv, IMX_MU_xCR, IMX_MU_xCR_RIEn(cp->bidx), 0);
> >> +
> >> +       return 0;
> >> +}
> >> +
> >> +static void imx_mu_shutdown(struct mbox_chan *chan)
> >> +{
> >> +       struct imx_mu_priv *priv = to_imx_mu_priv(chan->mbox);
> >> +       struct imx_mu_con_priv *cp = chan->con_priv;
> >> +
> >> +       imx_mu_rmw(priv, IMX_MU_xCR, 0,
> >> +                  IMX_MU_xCR_TIEn(cp->bidx) | IMX_MU_xCR_RIEn(cp->bidx));
> >> +
> >> +       free_irq(cp->irq, chan);
> >> +}
> >> +
> >> +static const struct mbox_chan_ops imx_mu_ops = {
> >> +       .send_data = imx_mu_send_data,
> >> +       .startup = imx_mu_startup,
> >> +       .shutdown = imx_mu_shutdown,
> >> +       .last_tx_done = imx_mu_last_tx_done,
> >
> > Do we really need this?
> > Looking at the code, it seems .last_tx_done() is only called for polling mode.
> > But what you set below is:
> > priv->mbox.txdone_irq = true;
> >
> > Or am i missed something?
> >
> >> +};
> >> +
> >> +static int imx_mu_probe(struct platform_device *pdev)
> >> +{
> >> +       struct device *dev = &pdev->dev;
> >> +       struct resource *iomem;
> >> +       struct imx_mu_priv *priv;
> >> +       const struct imx_mu_cfg *dcfg;
> >> +       unsigned int i, chans;
> >> +       int irq, ret;
> >> +
> >> +       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> >> +       if (!priv)
> >> +               return -ENOMEM;
> >> +
> >> +       dcfg = of_device_get_match_data(dev);
> >> +       if (!dcfg)
> >> +               return -EINVAL;
> >> +
> >> +       priv->dcfg = dcfg;
> >> +       priv->dev = dev;
> >> +
> >> +       iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> >> +       priv->base = devm_ioremap_resource(&pdev->dev, iomem);
> >> +       if (IS_ERR(priv->base))
> >> +               return PTR_ERR(priv->base);
> >> +
> >> +       irq = platform_get_irq(pdev, 0);
> >> +       if (irq <= 0)
> >> +               return irq < 0 ? irq : -EINVAL;
> >
> > Is it possible == 0?
> >
> >> +
> >> +       priv->clk = devm_clk_get(dev, NULL);
> >> +       if (IS_ERR(priv->clk)) {
> >> +               if (PTR_ERR(priv->clk) == -ENOENT) {
> >> +                       priv->clk = NULL;
> >> +               } else {
> >> +                       dev_err(dev, "Failed to get clock\n");
> >
> > The line looks not be quite meaningful as it may be defer probe.
> >
> >> +                       return PTR_ERR(priv->clk);
> >> +               }
> >> +       }
> >> +
> >> +       ret = clk_prepare_enable(priv->clk);
> >> +       if (ret) {
> >> +               dev_err(dev, "Failed to enable clock\n");
> >> +               return ret;
> >> +       }
> >> +
> >> +       chans = min(dcfg->chans, IMX_MU_MAX_CHANS);
> >> +       /* Initialize channel identifiers */
> >> +       for (i = 0; i < chans; i++) {
> >> +               struct imx_mu_con_priv *cp = &priv->con_priv[i];
> >> +
> >> +               cp->bidx = 3 - i;
> >> +               cp->idx = i;
> >> +               cp->irq = irq;
> >> +               priv->mbox_chans[i].con_priv = cp;
> >> +       }
> >> +
> >> +       priv->mbox.dev = dev;
> >> +       priv->mbox.ops = &imx_mu_ops;
> >> +       priv->mbox.chans = priv->mbox_chans;
> >> +       priv->mbox.num_chans = chans;
> >> +       priv->mbox.txdone_irq = true;
> >> +
> >> +       platform_set_drvdata(pdev, priv);
> >> +
> >> +       if (priv->dcfg->init_hw)
> >> +               priv->dcfg->init_hw(priv);
> >> +
> >> +       return mbox_controller_register(&priv->mbox);
> >> +}
> >> +
> >> +static int imx_mu_remove(struct platform_device *pdev)
> >> +{
> >> +       struct imx_mu_priv *priv = platform_get_drvdata(pdev);
> >> +
> >> +       mbox_controller_unregister(&priv->mbox);
> >> +       clk_disable_unprepare(priv->clk);
> >> +
> >> +       return 0;
> >> +}
> >> +
> >> +
> >> +static void imx_mu_init_imx7d_a(struct imx_mu_priv *priv)
> >> +{
> >> +       /* Set default config */
> >> +       imx_mu_write(priv, 0, IMX_MU_xCR);
> >> +}
> >> +
> >> +static const struct imx_mu_cfg imx_mu_cfg_imx7d_a = {
> >> +       .chans = IMX_MU_MAX_CHANS,
> >> +       .init_hw = imx_mu_init_imx7d_a,
> >> +};
> >> +
> >> +static const struct imx_mu_cfg imx_mu_cfg_imx7d_b = {
> >> +       .chans = IMX_MU_MAX_CHANS,
> >> +};
> >> +
> >> +static const struct of_device_id imx_mu_dt_ids[] = {
> >> +       { .compatible = "fsl,imx7s-mu-a", .data = &imx_mu_cfg_imx7d_a },
> >> +       { .compatible = "fsl,imx7s-mu-b", .data = &imx_mu_cfg_imx7d_b },
> >> +       { },
> >> +};
> >> +MODULE_DEVICE_TABLE(of, imx_mu_dt_ids);
> >> +
> >> +static struct platform_driver imx_mu_driver = {
> >> +       .probe          = imx_mu_probe,
> >> +       .remove         = imx_mu_remove,
> >> +       .driver = {
> >> +               .name   = "imx_mu",
> >> +               .of_match_table = imx_mu_dt_ids,
> >> +       },
> >> +};
> >> +module_platform_driver(imx_mu_driver);
> >> +
> >> +MODULE_AUTHOR("Oleksij Rempel <o.rempel@pengutronix.de>");
> >> +MODULE_DESCRIPTION("Message Unit driver for i.MX7");
> >
> > s/i.MX7/i.MX
> >
> > Regards
> > Dong Aisheng
> >
> >> +MODULE_LICENSE("GPL v2");
> >> --
> >> 2.17.1
> >>
> >> --
> >> To unsubscribe from this list: send the line "unsubscribe linux-clk" in
> >> the body of a message to majordomo at vger.kernel.org
> >> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
> 

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180615/eee47033/attachment-0001.sig>

^ permalink raw reply	[flat|nested] 54+ messages in thread

end of thread, other threads:[~2018-06-15  6:23 UTC | newest]

Thread overview: 54+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-06-01  6:58 [PATCH v1 0/4] add mailbox support for i.MX7D Oleksij Rempel
2018-06-01  6:58 ` Oleksij Rempel
2018-06-01  6:58 ` Oleksij Rempel
2018-06-01  6:58 ` [PATCH v1 1/4] clk: imx7d: add IMX7D_MU_ROOT_CLK Oleksij Rempel
2018-06-01  6:58   ` Oleksij Rempel
2018-06-01  6:58   ` Oleksij Rempel
2018-06-13 10:38   ` Dong Aisheng
2018-06-13 10:38     ` Dong Aisheng
2018-06-13 10:38     ` Dong Aisheng
2018-06-01  6:58 ` [PATCH v1 2/4] dt-bindings: mailbox: provide imx-mailbox documentation Oleksij Rempel
2018-06-01  6:58   ` Oleksij Rempel
2018-06-01  6:58   ` Oleksij Rempel
2018-06-12 19:41   ` Rob Herring
2018-06-12 19:41     ` Rob Herring
2018-06-12 19:41     ` Rob Herring
2018-06-13 11:59     ` Oleksij Rempel
2018-06-13 11:59       ` Oleksij Rempel
2018-06-13 11:59       ` Oleksij Rempel
2018-06-13 11:05   ` Dong Aisheng
2018-06-13 11:05     ` Dong Aisheng
2018-06-13 11:05     ` Dong Aisheng
2018-06-13 11:58     ` Oleksij Rempel
2018-06-13 11:58       ` Oleksij Rempel
2018-06-13 11:58       ` Oleksij Rempel
2018-06-01  6:58 ` [PATCH v1 3/4] ARM: dts: imx7s: add i.MX7 messaging unit support Oleksij Rempel
2018-06-01  6:58   ` Oleksij Rempel
2018-06-01  6:58   ` Oleksij Rempel
2018-06-01  6:58 ` [PATCH v1 4/4] mailbox: Add support for i.MX7D messaging unit Oleksij Rempel
2018-06-01  6:58   ` Oleksij Rempel
2018-06-01  6:58   ` Oleksij Rempel
2018-06-13 12:21   ` Dong Aisheng
2018-06-13 12:21     ` Dong Aisheng
2018-06-13 12:21     ` Dong Aisheng
2018-06-13 12:24     ` Dong Aisheng
2018-06-13 12:24       ` Dong Aisheng
2018-06-13 12:24       ` Dong Aisheng
2018-06-15  6:23       ` Oleksij Rempel
2018-06-15  6:23         ` Oleksij Rempel
2018-06-15  6:23         ` Oleksij Rempel
2018-06-13 12:48     ` Sascha Hauer
2018-06-13 12:48       ` Sascha Hauer
2018-06-13 12:48       ` Sascha Hauer
2018-06-14  8:23       ` Dong Aisheng
2018-06-14  8:23         ` Dong Aisheng
2018-06-14  8:23         ` Dong Aisheng
2018-06-14 10:24     ` Oleksij Rempel
2018-06-14 10:24       ` Oleksij Rempel
2018-06-14 10:24       ` Oleksij Rempel
2018-06-01  8:34 ` [PATCH v1 0/4] add mailbox support for i.MX7D Robert Schwebel
2018-06-01  8:34   ` Robert Schwebel
2018-06-01  8:34   ` Robert Schwebel
2018-06-13  9:36   ` A.s. Dong
2018-06-13  9:36     ` A.s. Dong
2018-06-13  9:36     ` A.s. Dong

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.