spi more than 4 chipselects on imx6

cancel
Showing results for 
Search instead for 
Did you mean: 

spi more than 4 chipselects on imx6

2,592 Views
joshuaclayton
Contributor III

I have an imx6q based board, which was designed with 6 devices connected to ecspi4.

conencting these to a different spi bus would be problematic for various reasons, and since we are using gpio chipselects, it seems like more than 4 spi devices ought to be supportable.

I have made an attempt that mostly works. I let cs0, cs1, and cs2 work the same as they always have, and reuse cs3 for cs3, cs4 and cs5:

The only problem is this shared cs3 arrangement make the spi master unreliable. calls to write to spi sometimes work and sometimes don't.

I am also observing that the CLK line for the spi seems to be active when it should not be, (possibly the source of instability). One of the devices sharing cs3 is a cs-active-high device, so this might contribute to the problem if there is some internal hardware state that think the same device is being accessed when it is not.

I also (less successfully) tried to reset the spi control register at the beginning of mx51_ecspi_config

Here is my patch:

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c

index 3637847..751574c 100644

--- a/drivers/spi/spi-imx.c

+++ b/drivers/spi/spi-imx.c

@@ -314,6 +314,12 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx,

        u32 ctrl = MX51_ECSPI_CTRL_ENABLE, cfg = 0, dma = 0;

        u32 tx_wml_cfg, rx_wml_cfg, rxt_wml_cfg;

        u32 clk = config->speed_hz, delay;

+       u8 cs;

+

+       if (config->cs < 3)

+               cs = config->cs;

+       else

+               cs = 3;

        /*

         * The hardware seems to have a race condition when changing modes. The

@@ -328,21 +334,21 @@ static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx,

        ctrl |= mx51_ecspi_clkdiv(spi_imx->spi_clk, config->speed_hz, &clk);

        /* set chip select to use */

-       ctrl |= MX51_ECSPI_CTRL_CS(config->cs);

+       ctrl |= MX51_ECSPI_CTRL_CS(cs);

        ctrl |= (config->bpw - 1) << MX51_ECSPI_CTRL_BL_OFFSET;

-       cfg |= MX51_ECSPI_CONFIG_SBBCTRL(config->cs);

+       cfg |= MX51_ECSPI_CONFIG_SBBCTRL(cs);

        if (config->mode & SPI_CPHA)

-               cfg |= MX51_ECSPI_CONFIG_SCLKPHA(config->cs);

+               cfg |= MX51_ECSPI_CONFIG_SCLKPHA(cs);

        if (config->mode & SPI_CPOL) {

-               cfg |= MX51_ECSPI_CONFIG_SCLKPOL(config->cs);

-               cfg |= MX51_ECSPI_CONFIG_SCLKCTL(config->cs);

+               cfg |= MX51_ECSPI_CONFIG_SCLKPOL(cs);

+               cfg |= MX51_ECSPI_CONFIG_SCLKCTL(cs);

        }

        if (config->mode & SPI_CS_HIGH)

-               cfg |= MX51_ECSPI_CONFIG_SSBPOL(config->cs);

+               cfg |= MX51_ECSPI_CONFIG_SSBPOL(cs);

        writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL);

        writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG);

Any thoughts on what I might try next would be appreciated.

0 Kudos
5 Replies

823 Views
fabio_estevam
NXP Employee
NXP Employee

If one of the chip selects needs to be active high you need to pass "spi-cs-high" property.

Take a look at: Documentation/devicetree/bindings/spi/spi-bus.txt and also at arch/arm/boot/dts/imx51-babbage.dts for an example.

0 Kudos

823 Views
joshuaclayton
Contributor III

I have set the chipselect appropriately for that device ( the nxp rtc-pcf2123)

In fact I know the the spi configurations for each device are correct individually, because if I take out any two, the remaining 4 devices function as expected.

With an unmodified spi-imx.c, accessing the 5th or 6th device results in an unkillable spidev_test process, and permantly locking up the spi master (until reboot).

Noting that the spi-imx.c driver bitshifts config options by the chipselect id, it cannot possibly work with more than 4 chipselects.

for reference, my spi dts section:

&ecspi5 {

        fsl,spi-num-chipselects = <6>;

        cs-gpios = <&gpio1 14 GPIO_ACTIVE_LOW>,

                <&gpio1 13 GPIO_ACTIVE_LOW>,

                <&gpio1 12 GPIO_ACTIVE_LOW>,

                <&gpio2 9 GPIO_ACTIVE_HIGH>,

                <&gpio7 6 GPIO_ACTIVE_LOW>,

                <&gpio7 7 GPIO_ACTIVE_LOW>;

        pinctrl-names = "default";

        pinctrl-0 = <&pinctrl_ecspi5 &pinctrl_ecspi5_cs>;

        status = "okay";

        pwr_mcu: lpc1227@0 {

                compatible = "uniwest,evi-pb";

                spi-max-frequency = <2450000>;

                reg = <0>;

        };

        pb_flash: m25p80@1 {

                compatible = "spidev";

                spi-max-frequency = <2450000>;

                reg = <1>;

        };

        temp0: temp@3 {

                compatible = "spidev";

                spi-max-frequency = <2450000>;

                reg = <2>;

        };

        pb_rtc: rtc@2 {

                compatible = "nxp,rtc-pcf2123";

                spi-max-frequency = <2450000>;

                spi-cs-high;

                reg = <3>;

        };

        temp1: temp@4 {

                compatible = "spidev";

                spi-max-frequency = <2450000>;

                reg = <4>;

        };

        lvds_dim: lvds_dim@5 {

                compatible = "spidev";

                spi-max-frequency = <2450000>;

                reg = <5>;

        };

};

&ecspi5 {

        fsl,spi-num-chipselects = <6>;

        cs-gpios = <&gpio1 14 GPIO_ACTIVE_LOW>,

                <&gpio1 13 GPIO_ACTIVE_LOW>,

                <&gpio1 12 GPIO_ACTIVE_LOW>,

                <&gpio2 9 GPIO_ACTIVE_HIGH>,

                <&gpio7 6 GPIO_ACTIVE_LOW>,

                <&gpio7 7 GPIO_ACTIVE_LOW>;

        pinctrl-names = "default";

        pinctrl-0 = <&pinctrl_ecspi5 &pinctrl_ecspi5_cs>;

        status = "okay";

        pwr_mcu: lpc1227@0 {

                compatible = "uniwest,evi-pb";

                spi-max-frequency = <2450000>;

                reg = <0>;

        };

        pb_flash: m25p80@1 {

                compatible = "spidev";

                spi-max-frequency = <2450000>;

                reg = <1>;

        };

        temp0: temp@3 {

                compatible = "spidev";

                spi-max-frequency = <245000>;

                reg = <2>;

        };

        pb_rtc: rtc@2 {

                compatible = "nxp,rtc-pcf2123";

                spi-max-frequency = <2450000>;

                spi-cs-high;

                reg = <3>;

        };

        temp1: temp@4 {

                compatible = "spidev";

                spi-max-frequency = <2450000>;

                reg = <4>;

        };

        lvds_dim: lvds_dim@5 {

                compatible = "spidev";

                spi-max-frequency = <2450000>;

                reg = <5>;

        };

};

0 Kudos

823 Views
fabio_estevam
NXP Employee
NXP Employee

Just a comment about your dts: the @x number must match the reg = <x> field. It seems you swapped @2 and @3 nodes.

0 Kudos

478 Views
johnmxq
Contributor I

hello,i have three chip (ad7799),i have ad7799.ko ,when i ask first chip ,i write ./spi_test /dev/ad7799,but i ask second chip,how i write?

0 Kudos

823 Views
joshuaclayton
Contributor III

Thanks, Fabio.

I'm sure that the wrong addresses are the result of all the experimentation I was doing.

I fixed them and didn't see a change (though I didn't expect one).

0 Kudos