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]
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(-)
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(-)
@@ -175,8 +179,22 @@ static void meson_spicc_oen_enable(struct meson_spicc_device *spicc){u32conf;-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,elseconf&=~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);+return0;}
@@ -798,6 +829,12 @@ static int meson_spicc_probe(struct platform_device *pdev)gotoout_core_clk;}+spicc->pinctrl=devm_pinctrl_get(&pdev->dev);+if(IS_ERR(spicc->pinctrl)){+ret=PTR_ERR(spicc->pinctrl);+gotoout_clk;+}+device_reset_optional(&pdev->dev);master->num_chipselect=4;
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.
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.
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
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
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.
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.
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
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
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 ?