[PATCH v3 0/2] spi: amlogic: meson-spicc: Use pinctrl to drive CLK line when idle

STALE1452d SUPERSEDED

Revision v3 of 4 in this series.

11 messages, 5 authors, 2022-10-21 · open the first message on its own page

[PATCH v3 0/2] spi: amlogic: meson-spicc: Use pinctrl to drive CLK line when idle

From: Amjad Ouled-Ameur <hidden>
Date: 2022-10-19 14:21:30

Between SPI transactions, all SPI pins are in HiZ state. When using the SS
signal from the SPICC controller it's not an issue because when the
transaction resumes all pins come back to the right state at the same time
as SS.

The problem is when we use CS as a GPIO. In fact, between the GPIO CS
state change and SPI pins state change from idle, you can have a missing or
spurious clock transition.

Set a bias on the clock depending on the clock polarity requested before CS
goes active, by passing a special "idle-low" and "idle-high" pinctrl state
and setting the right state at a start of a message.

Signed-off-by: Amjad Ouled-Ameur <redacted>
---
Changes in v3:
- Fixed documentation by removing pinctrl states as they are not mandatory.
- Link to v2: https://lore.kernel.org/r/20221004-up-aml-fix-spi-v2-0-3e8ae91a1925@baylibre.com

---
Amjad Ouled-Ameur (2):
      spi: dt-bindings: amlogic, meson-gx-spicc: Add pinctrl names for SPI signal states
      spi: meson-spicc: Use pinctrl to drive CLK line when idle

 .../bindings/spi/amlogic,meson-gx-spicc.yaml       | 67 ++++++++++++++--------
 arch/arm64/boot/dts/amlogic/meson-gxl.dtsi         | 14 +++++
 drivers/spi/spi-meson-spicc.c                      | 39 ++++++++++++-
 3 files changed, 94 insertions(+), 26 deletions(-)
---
base-commit: aae703b02f92bde9264366c545e87cec451de471
change-id: 20221004-up-aml-fix-spi-c2bb7e78e603

Best regards,
-- 
Amjad Ouled-Ameur [off-list ref]

[PATCH v3 1/2] spi: dt-bindings: amlogic, meson-gx-spicc: Add pinctrl names for SPI signal states

From: Amjad Ouled-Ameur <hidden>
Date: 2022-10-19 14:21:34

SPI pins of the SPICC Controller in Meson-GX needs to be controlled by
pin biais when idle. Therefore define three pinctrl names:
- default: SPI pins are controlled by spi function.
- idle-high: SCLK pin is pulled-up, but MOSI/MISO are still controlled
by spi function.
- idle-low: SCLK pin is pulled-down, but MOSI/MISO are still controlled
by spi function.

Reported-by: Da Xue <redacted>
Signed-off-by: Neil Armstrong <redacted>
Signed-off-by: Amjad Ouled-Ameur <redacted>
---
 .../bindings/spi/amlogic,meson-gx-spicc.yaml       | 67 ++++++++++++++--------
 1 file changed, 42 insertions(+), 25 deletions(-)
diff --git a/Documentation/devicetree/bindings/spi/amlogic,meson-gx-spicc.yaml b/Documentation/devicetree/bindings/spi/amlogic,meson-gx-spicc.yaml
index 0c10f7678178..3e47fe7760a8 100644
--- a/Documentation/devicetree/bindings/spi/amlogic,meson-gx-spicc.yaml
+++ b/Documentation/devicetree/bindings/spi/amlogic,meson-gx-spicc.yaml
@@ -43,31 +43,48 @@ properties:
     minItems: 1
     maxItems: 2
 
-if:
-  properties:
-    compatible:
-      contains:
-        enum:
-          - amlogic,meson-g12a-spicc
-
-then:
-  properties:
-    clocks:
-      minItems: 2
-
-    clock-names:
-      items:
-        - const: core
-        - const: pclk
-
-else:
-  properties:
-    clocks:
-      maxItems: 1
-
-    clock-names:
-      items:
-        - const: core
+allOf:
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - amlogic,meson-g12a-spicc
+
+    then:
+      properties:
+        clocks:
+          minItems: 2
+
+        clock-names:
+          items:
+            - const: core
+            - const: pclk
+
+    else:
+      properties:
+        clocks:
+          maxItems: 1
+
+        clock-names:
+          items:
+            - const: core
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - amlogic,meson-gx-spicc
+
+    then:
+      properties:
+        pinctrl-names:
+          minItems: 1
+          items:
+            - const: default
+            - const: idle-high
+            - const: idle-low
 
 required:
   - compatible
-- 
b4 0.10.1

[PATCH v3 2/2] spi: meson-spicc: Use pinctrl to drive CLK line when idle

From: Amjad Ouled-Ameur <hidden>
Date: 2022-10-19 14:22:05

Between SPI transactions, all SPI pins are in HiZ state. When using the SS
signal from the SPICC controller it's not an issue because when the
transaction resumes all pins come back to the right state at the same time
as SS.

The problem is when we use CS as a GPIO. In fact, between the GPIO CS
state change and SPI pins state change from idle, you can have a missing or
spurious clock transition.

Set a bias on the clock depending on the clock polarity requested before CS
goes active, by passing a special "idle-low" and "idle-high" pinctrl state
and setting the right state at a start of a message

Reported-by: Da Xue <redacted>
Signed-off-by: Neil Armstrong <redacted>
Signed-off-by: Amjad Ouled-Ameur <redacted>
---
 arch/arm64/boot/dts/amlogic/meson-gxl.dtsi | 14 +++++++++++
 drivers/spi/spi-meson-spicc.c              | 39 +++++++++++++++++++++++++++++-
 2 files changed, 52 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
index c3ac531c4f84..04e9d0f1bde0 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
@@ -429,6 +429,20 @@ mux {
 			};
 		};
 
+		spi_idle_high_pins: spi-idle-high-pins {
+			mux {
+				groups = "spi_sclk";
+				bias-pull-up;
+			};
+		};
+
+		spi_idle_low_pins: spi-idle-low-pins {
+			mux {
+				groups = "spi_sclk";
+				bias-pull-down;
+			};
+		};
+
 		spi_ss0_pins: spi-ss0 {
 			mux {
 				groups = "spi_ss0";
diff --git a/drivers/spi/spi-meson-spicc.c b/drivers/spi/spi-meson-spicc.c
index bad201510a99..ffea38e2339c 100644
--- a/drivers/spi/spi-meson-spicc.c
+++ b/drivers/spi/spi-meson-spicc.c
@@ -21,6 +21,7 @@
 #include <linux/types.h>
 #include <linux/interrupt.h>
 #include <linux/reset.h>
+#include <linux/pinctrl/consumer.h>
 
 /*
  * The Meson SPICC controller could support DMA based transfers, but is not
@@ -167,6 +168,9 @@ struct meson_spicc_device {
 	unsigned long			tx_remain;
 	unsigned long			rx_remain;
 	unsigned long			xfer_remain;
+	struct pinctrl			*pinctrl;
+	struct pinctrl_state		*pins_idle_high;
+	struct pinctrl_state		*pins_idle_low;
 };
 
 #define pow2_clk_to_spicc(_div) container_of(_div, struct meson_spicc_device, pow2_div)
@@ -175,8 +179,22 @@ static void meson_spicc_oen_enable(struct meson_spicc_device *spicc)
 {
 	u32 conf;
 
-	if (!spicc->data->has_oen)
+	if (!spicc->data->has_oen) {
+		/* Try to get pinctrl states for idle high/low */
+		spicc->pins_idle_high = pinctrl_lookup_state(spicc->pinctrl,
+							     "idle-high");
+		if (IS_ERR(spicc->pins_idle_high)) {
+			dev_warn(&spicc->pdev->dev, "can't get idle-high pinctrl\n");
+			spicc->pins_idle_high = NULL;
+		}
+		spicc->pins_idle_low = pinctrl_lookup_state(spicc->pinctrl,
+							     "idle-low");
+		if (IS_ERR(spicc->pins_idle_low)) {
+			dev_warn(&spicc->pdev->dev, "can't get idle-low pinctrl\n");
+			spicc->pins_idle_low = NULL;
+		}
 		return;
+	}
 
 	conf = readl_relaxed(spicc->base + SPICC_ENH_CTL0) |
 		SPICC_ENH_MOSI_OEN | SPICC_ENH_CLK_OEN | SPICC_ENH_CS_OEN;
@@ -441,6 +459,16 @@ static int meson_spicc_prepare_message(struct spi_master *master,
 	else
 		conf &= ~SPICC_POL;
 
+	if (!spicc->data->has_oen) {
+		if (spi->mode & SPI_CPOL) {
+			if (spicc->pins_idle_high)
+				pinctrl_select_state(spicc->pinctrl, spicc->pins_idle_high);
+		} else {
+			if (spicc->pins_idle_low)
+				pinctrl_select_state(spicc->pinctrl, spicc->pins_idle_low);
+		}
+	}
+
 	if (spi->mode & SPI_CPHA)
 		conf |= SPICC_PHA;
 	else
@@ -487,6 +515,9 @@ static int meson_spicc_unprepare_transfer(struct spi_master *master)
 	/* Set default configuration, keeping datarate field */
 	writel_relaxed(conf, spicc->base + SPICC_CONREG);
 
+	if (!spicc->data->has_oen)
+		pinctrl_select_default_state(&spicc->pdev->dev);
+
 	return 0;
 }
 
@@ -798,6 +829,12 @@ static int meson_spicc_probe(struct platform_device *pdev)
 		goto out_core_clk;
 	}
 
+	spicc->pinctrl = devm_pinctrl_get(&pdev->dev);
+	if (IS_ERR(spicc->pinctrl)) {
+		ret = PTR_ERR(spicc->pinctrl);
+		goto out_clk;
+	}
+
 	device_reset_optional(&pdev->dev);
 
 	master->num_chipselect = 4;
-- 
b4 0.10.1

Re: [PATCH v3 1/2] spi: dt-bindings: amlogic, meson-gx-spicc: Add pinctrl names for SPI signal states

From: Krzysztof Kozlowski <hidden>
Date: 2022-10-19 14:44:51

On 19/10/2022 10:01, Amjad Ouled-Ameur wrote:
SPI pins of the SPICC Controller in Meson-GX needs to be controlled by
pin biais when idle. Therefore define three pinctrl names:
- default: SPI pins are controlled by spi function.
- idle-high: SCLK pin is pulled-up, but MOSI/MISO are still controlled
by spi function.
- idle-low: SCLK pin is pulled-down, but MOSI/MISO are still controlled
by spi function.
quoted hunk
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - amlogic,meson-gx-spicc
+
+    then:
+      properties:
+        pinctrl-names:
+          minItems: 1
+          items:
+            - const: default
+            - const: idle-high
+            - const: idle-low
You should also define in such case pinctrl-0 and others.

Best regards,
Krzysztof

Re: [PATCH v3 1/2] spi: dt-bindings: amlogic, meson-gx-spicc: Add pinctrl names for SPI signal states

From: Neil Armstrong <neil.armstrong@linaro.org>
Date: 2022-10-19 16:53:27

On 19/10/2022 16:29, Krzysztof Kozlowski wrote:
On 19/10/2022 10:01, Amjad Ouled-Ameur wrote:
quoted
SPI pins of the SPICC Controller in Meson-GX needs to be controlled by
pin biais when idle. Therefore define three pinctrl names:
- default: SPI pins are controlled by spi function.
- idle-high: SCLK pin is pulled-up, but MOSI/MISO are still controlled
by spi function.
- idle-low: SCLK pin is pulled-down, but MOSI/MISO are still controlled
by spi function.
quoted
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - amlogic,meson-gx-spicc
+
+    then:
+      properties:
+        pinctrl-names:
+          minItems: 1
+          items:
+            - const: default
+            - const: idle-high
+            - const: idle-low
You should also define in such case pinctrl-0 and others.
Ok I thought it would be covered by the pinctrl-consumer.yaml
but yeah we should allow pinctrl-1 and pinctrl-2 here aswell by adding:

            pinctrl-1: true
            pinctrl-2: true
Best regards,
Krzysztof
Neil

Re: [PATCH v3 2/2] spi: meson-spicc: Use pinctrl to drive CLK line when idle

From: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
Date: 2022-10-19 20:50:53

Hi Amjad,

On Wed, Oct 19, 2022 at 4:03 PM Amjad Ouled-Ameur
[off-list ref] wrote:
[...]
quoted hunk
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
index c3ac531c4f84..04e9d0f1bde0 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
@@ -429,6 +429,20 @@ mux {
                        };
                };

+               spi_idle_high_pins: spi-idle-high-pins {
+                       mux {
+                               groups = "spi_sclk";
+                               bias-pull-up;
+                       };
+               };
+
+               spi_idle_low_pins: spi-idle-low-pins {
+                       mux {
+                               groups = "spi_sclk";
+                               bias-pull-down;
+                       };
+               };
+
We typically have the .dts{,i} changes in a separate patch. I suggest
doing the same here.
I also have two questions about this part:
- why are these not referenced by the SPICC controller node?
- is there a particular reason why meson-gxl.dtsi is updated but
meson-gxbb.dtsi is not? (my understanding is that GXBB is also lacking
hardware OEN support)


Best regards,
Martin

Re: [PATCH v3 1/2] spi: dt-bindings: amlogic, meson-gx-spicc: Add pinctrl names for SPI signal states

From: Rob Herring <robh@kernel.org>
Date: 2022-10-19 23:32:20

On Wed, 19 Oct 2022 16:01:03 +0200, Amjad Ouled-Ameur wrote:
SPI pins of the SPICC Controller in Meson-GX needs to be controlled by
pin biais when idle. Therefore define three pinctrl names:
- default: SPI pins are controlled by spi function.
- idle-high: SCLK pin is pulled-up, but MOSI/MISO are still controlled
by spi function.
- idle-low: SCLK pin is pulled-down, but MOSI/MISO are still controlled
by spi function.

Reported-by: Da Xue <redacted>
Signed-off-by: Neil Armstrong <redacted>
Signed-off-by: Amjad Ouled-Ameur <redacted>
---
 .../bindings/spi/amlogic,meson-gx-spicc.yaml       | 67 ++++++++++++++--------
 1 file changed, 42 insertions(+), 25 deletions(-)
My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check'
on your patch (DT_CHECKER_FLAGS is new in v5.13):

yamllint warnings/errors:
./Documentation/devicetree/bindings/spi/amlogic,meson-gx-spicc.yaml:46:1: [error] duplication of key "allOf" in mapping (key-duplicates)

dtschema/dtc warnings/errors:
./Documentation/devicetree/bindings/spi/amlogic,meson-gx-spicc.yaml:46:1: found duplicate key "allOf" with value "[]" (original value: "[]")
/builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/spi/amlogic,meson-gx-spicc.yaml: ignoring, error parsing file
make[1]: *** Deleting file 'Documentation/devicetree/bindings/spi/amlogic,meson-gx-spicc.example.dts'
Documentation/devicetree/bindings/spi/amlogic,meson-gx-spicc.yaml:46:1: found duplicate key "allOf" with value "[]" (original value: "[]")
make[1]: *** [Documentation/devicetree/bindings/Makefile:26: Documentation/devicetree/bindings/spi/amlogic,meson-gx-spicc.example.dts] Error 1
make[1]: *** Waiting for unfinished jobs....
make: *** [Makefile:1492: dt_binding_check] Error 2

doc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/patch/

This check can fail if there are any dependencies. The base for a patch
series is generally the most recent rc1.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit.

Re: [PATCH v3 2/2] spi: meson-spicc: Use pinctrl to drive CLK line when idle

From: Neil Armstrong <neil.armstrong@linaro.org>
Date: 2022-10-20 08:18:30

On 19/10/2022 22:50, Martin Blumenstingl wrote:
Hi Amjad,

On Wed, Oct 19, 2022 at 4:03 PM Amjad Ouled-Ameur
[off-list ref] wrote:
[...]
quoted
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
index c3ac531c4f84..04e9d0f1bde0 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
@@ -429,6 +429,20 @@ mux {
                         };
                 };

+               spi_idle_high_pins: spi-idle-high-pins {
+                       mux {
+                               groups = "spi_sclk";
+                               bias-pull-up;
+                       };
+               };
+
+               spi_idle_low_pins: spi-idle-low-pins {
+                       mux {
+                               groups = "spi_sclk";
+                               bias-pull-down;
+                       };
+               };
+
We typically have the .dts{,i} changes in a separate patch. I suggest
doing the same here.
I also have two questions about this part:
- why are these not referenced by the SPICC controller node?
Because it's up to the board to use or not those states, if some pull-up/downs
are already present on the lines no need to use those special states.
- is there a particular reason why meson-gxl.dtsi is updated but
meson-gxbb.dtsi is not? (my understanding is that GXBB is also lacking
hardware OEN support)
Good question indeed, so indeed they should be added in meson-gxbb.dtsi in a separate patch.

Best regards,
Martin
Thanks,
Neil

Re: [PATCH v3 1/2] spi: dt-bindings: amlogic, meson-gx-spicc: Add pinctrl names for SPI signal states

From: Krzysztof Kozlowski <hidden>
Date: 2022-10-20 12:49:27

quoted
quoted
+      properties:
+        pinctrl-names:
+          minItems: 1
+          items:
+            - const: default
+            - const: idle-high
+            - const: idle-low
You should also define in such case pinctrl-0 and others.
Ok I thought it would be covered by the pinctrl-consumer.yaml
but yeah we should allow pinctrl-1 and pinctrl-2 here aswell by adding:

             pinctrl-1: true
             pinctrl-2: true
Yes.

Best regards,
Krzysztof

Re: [PATCH v3 1/2] spi: dt-bindings: amlogic, meson-gx-spicc: Add pinctrl names for SPI signal states

From: Amjad Ouled-Ameur <hidden>
Date: 2022-10-21 12:54:22

Hi

On 10/20/22 14:49, Krzysztof Kozlowski wrote:
quoted
quoted
quoted
+      properties:
+        pinctrl-names:
+          minItems: 1
+          items:
+            - const: default
+            - const: idle-high
+            - const: idle-low
You should also define in such case pinctrl-0 and others.
Ok I thought it would be covered by the pinctrl-consumer.yaml
but yeah we should allow pinctrl-1 and pinctrl-2 here aswell by adding:

              pinctrl-1: true
              pinctrl-2: true
In such case, should I define pinctrl- as part of the if statement, as shown below,

or before allOf ?

[...]

  - if:
      properties:
        compatible:
          contains:
            enum:
              - amlogic,meson-gx-spicc

    then:
      properties:
        pinctrl-0: true
        pinctrl-1: true
        pinctrl-2: true

        pinctrl-names:
          minItems: 1
          items:
            - const: default
            - const: idle-high
            - const: idle-low

[...]

Regards

Amjad
Yes.

Best regards,
Krzysztof

Re: [PATCH v3 1/2] spi: dt-bindings: amlogic, meson-gx-spicc: Add pinctrl names for SPI signal states

From: Krzysztof Kozlowski <hidden>
Date: 2022-10-21 12:59:59

On 21/10/2022 08:54, Amjad Ouled-Ameur wrote:
Hi

On 10/20/22 14:49, Krzysztof Kozlowski wrote:
quoted
quoted
quoted
quoted
+      properties:
+        pinctrl-names:
+          minItems: 1
+          items:
+            - const: default
+            - const: idle-high
+            - const: idle-low
You should also define in such case pinctrl-0 and others.
Ok I thought it would be covered by the pinctrl-consumer.yaml
but yeah we should allow pinctrl-1 and pinctrl-2 here aswell by adding:

              pinctrl-1: true
              pinctrl-2: true
In such case, should I define pinctrl- as part of the if statement, as shown below,

or before allOf ?
The same as pinctrl-names, so part of allOf.
[...]

   - if:
       properties:
         compatible:
           contains:
             enum:
               - amlogic,meson-gx-spicc

     then:
       properties:
         pinctrl-0: true
         pinctrl-1: true
         pinctrl-2: true

         pinctrl-names:
           minItems: 1
           items:
             - const: default
             - const: idle-high
             - const: idle-low
Best regards,
Krzysztof
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help