i.MX6ULL SPI CS not working when using GPIO

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

i.MX6ULL SPI CS not working when using GPIO

682 Views
paul_geurts
Contributor III

Hi all,

We are running NXP's Linux 5.4.24_2.1.0 release on a custom i.MX6ULL board. We have an SPI-NOR flash device connected to ECSPI1 and use the #CS line as GPIO. From DTS point of view it looks like:

/* Recovery flash */
&ecspi1 {
  pinctrl-names = "default";
  pinctrl-0 = <&pinctrl_ecspi1>;
  status = "okay";
  cs-gpios = <&gpio4 26 GPIO_ACTIVE_LOW>;

  flash@0 {
    address-cells = <1>;
    size-cells = <1>;
    reg = <0>;
    compatible = "jedec,spi-nor";
    spi-max-frequency = <12500000>;
    status = "okay";
    partition@0x00000000 {
      label = "recovery_boot";
      reg = <0x00000000 0x00100000>;
    };
    partition@0x00100000 {
      label = "recovery_fw";
      reg = <0x00100000 0x00680000>;
    };
    partition@0x00780000 {
      label = "factory_data";
      reg = <0x00780000 0x00080000>;
    };
  };
};

pinctrl_ecspi1: ecspi1grp-1 {
  fsl,pins = <
    MX6UL_PAD_CSI_DATA04__ECSPI1_SCLK       0x10b0
    MX6UL_PAD_CSI_DATA05__GPIO4_IO26        0x10b0 /* CS# */
    MX6UL_PAD_CSI_DATA06__ECSPI1_MOSI       0x10b0
    MX6UL_PAD_CSI_DATA07__ECSPI1_MISO       0x10b0
  >;
 };

 This does not work during boot, and we found out the CS pin is not being pulled low during a read of the flash chip. After a lot of digging is seems the kernel is trying to drive the GPIO, but it just doesn't do anything.

We dug around in the GPIO driver (gpio-mmio.c) to find what it is actually trying to do, but it seems the GPIO driver is in some sort of limbo state at the moment the SPI driver is trying to toggle the CS GPIO. When it tries to set the i.MX6ULL GPIO registers, the value written to the registers is not actually going into these registers. We tested this by setting the GPIO_GDIR register to 0x00000000 (all input) for the used bank from U-Boot, boot Linux and check the register value again (via /dev/mem). As you can see with my added debug prints, after kernel boot, the SPI driver should have set the GDIR register (offset 0x04) to 0x04000000:
init.png

But after reading the register after boot using /dev/mem, it didn't actually set the register:
linux-md.png

We have no idea why this happens. We did find it to be heavily influenced by the order of initialization of the SPI devices. The SPI subsystem is setup in a way that when an SPI controller is registered, the SPI devices connected to this controller (in this case the spi-nor device) are immediately initialized during the SPI controller probe. When we delay the device register until the controller probe has been finished, everything is fine, CS works and the NOR flash device is working fine. We tested this by compiling both spi-imx.c and spi-nor.c as modules and inserting them after boot. we found:

insmod spi-nor.ko && insmod spi-imx.ko

results in the same failure as shown above.

insmod spi-imx.ko && insmod spi-nor.ko

works fine, as the spi device is registered and initialized _after_ the spi_imx probe is fully completed.

We have no idea what is going on or how to fix this behavior. Has anyone seen this before? How did you fix it?

Some additional notes and research we already did:

  • This issue is not related to the issue described in This community thread 
  • We are using GPIO instead of native CS because our SPI device is 16-bit, which doesn't work with native CS, as reported here 
  • Using a full bitbang SPI controller with GPIOs for MOSI, MISO, SCLK and CS works without issues, which provides an indication that this issue is somewhere in the spi-imx driver. However, a full bitbang SPI controller is a usable solution due to performance issues.
  • Before our custom board was finished, we did some preliminary tests on the Colibri module from Toradex, using the Toradex Linux kernel,  version toradex_5.4-2.3.x-imx. This kernel/board had the same issues with SPI devices.

Thanks for the help!

0 Kudos
1 Reply

477 Views
YDD
Contributor I

Hello,

Have you find a workaround ?

I'm in the same case with my iMX6ULL board.

Kind regards

0 Kudos