AnsweredAssumed Answered

i.MX7D ECSPI problems in PIO mode

Question asked by Botond Kardos on Oct 17, 2018
Latest reply on Oct 18, 2018 by Botond Kardos

Hello,

while making a TPM2.0 SPI module work with i.MX7D I have encountered some problems. For some reason I'm not able to start DMA so everything below refers to PIO mode.

First I think there's either a problem with the ECSPI module or the i.MX7D reference manual (RM) isn't accurate. For TPM2.0 I would need longer bursts with a single contiguous CS impulse. The RM gives an example on this exact same use case (in 10.1.4.4.1.3) but elsewhere it is ambiguous. In 10.1.7.4 the comment for the SS_CTL[] states "0 - only one SPI burst will be transmitted". And this seems to be the reality: if I fill the FIFO, clear SS_CTL[0] and set XCH, I will see a single SPI burst on the oscilloscope, an interrupt will be triggered and XCH bit is already cleared when the interrupt hits. Using SMC instead of XCH results in multiple discrete SPI bursts but all with a separate pulse on SS0 (the chip-select line).

So it seems to me that it is not possible to generate multiple SPI bursts with a single SS0 pulse (at least not the way it is described in the RM).

 

So I went for a GPIO solution: I wanted to set and clear SS0 from SW and done automatically by the ECSPI module.

Here came another problem: spi-imx.c configures the cs_gpio pin as an output too early (before it has been requested for) so it doesn't give out any pulses. (I have properly modified the device tree.)

I needed to add this patch (to 4.9.88 BSP):

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 284a0de..7b46ba1 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -339,6 +339,10 @@ static void mx51_ecspi_trigger(struct spi_imx_data *spi_imx)
                reg |= MX51_ECSPI_CTRL_SMC;
        else
                reg &= ~MX51_ECSPI_CTRL_SMC;
+
+    reg &= ~MX51_ECSPI_CTRL_XCH;
+    reg |= MX51_ECSPI_CTRL_SMC;
+
        writel(reg, spi_imx->base + MX51_ECSPI_CTRL);
 }
 
@@ -1297,6 +1306,7 @@ static int spi_imx_probe(struct platform_device *pdev)
                goto out_clk_put;
        }
 
+    spi = to_spi_device( spi_imx->dev );
        for (i = 0; i < master->num_chipselect; i++) {
                if (!gpio_is_valid(master->cs_gpios[i]))
                        continue;
@@ -1308,6 +1318,13 @@ static int spi_imx_probe(struct platform_device *pdev)
                                master->cs_gpios[i]);
                        goto out_clk_put;
                }
+
+        if ( spi ) {
+            ret = gpio_direction_output(master->cs_gpios[i],
+                                        spi->mode & SPI_CS_HIGH ? 0 : 1);
+            printk( KERN_ALERT "**** gpio_direction_output: %i\n", ret );
+        } else
+            printk( KERN_ALERT "**** spi == NULL\n" );
        }
 
        dev_info(&pdev->dev, "probed\n");

(One may omit my "printk" messages.)

 

It seems to me that the latest stable kernel also has this issue. spi-imx.c configures cs_gpio as output in spi_imx_setup() but that will be called before devm_gpio_request() for the same pin.

As mentioned above all this applies to non-DMA case.

/Botond

Outcomes