Jump to content

spi gpio chip select support


Mike R9FT

Recommended Posts

Is it possible to add some gpio chip select for support more than one chip select on board ?

Loooked on https://github.com/armbian/linux ... ers/spi/spi-sunxi.c
I am not found any support of gpio here.

 

Also here https://github.com/armbian/linux/blob/sun8i/drivers/spi/spi-sunxi.h we can see that only one chip select can be used:

 

/* About CS */

#ifdef CONFIG_ARCH_SUN8IW1P1
#define SUNXI_CS_BITMAP(ch)     (ch%2 == 0 ? 1 : 3)
#define SUNXI_CS_NUM(ch)        (ch%2 == 0 ? 1 : 2)
#endif
#ifdef CONFIG_ARCH_SUN9IW1P1
#define SUNXI_CS_BITMAP(ch)     (ch == 3 ? 7 : 1)
#define SUNXI_CS_NUM(ch)        (ch == 3 ? 4 : 1)
#endif

#ifndef SUNXI_CS_BITMAP
#define SUNXI_CS_BITMAP(ch)     1
#define SUNXI_CS_NUM(ch)        1
#endif


Any suggestions?

May be someone knows if it is working in other kernel version (for example https://github.com/megous/linux/) ?


Thanks

Link to comment
Share on other sites

Thank you.

 

I get it working on mainline (Armbian_5.27.170521_Orangepione_Ubuntu_xenial_dev_4.11.1.7z) with ads7846 (xpt2046 touch with 5" hdmi display) and spidev (ADC mcp3204 connected).

Also rtc ds1307 connected to i2c.

 

My armbianEnv.txt adds:

overlays=spi-spidev i2c0
param_spidev_spi_bus=0
user_overlays=cs1 sun8i-h3-spi-ads7846 ds1307

cs1.dts

/dts-v1/;
/plugin/;

/ {
        compatible = "allwinner,sun8i-h3";

        fragment@0 {
                target = <&pio>;
                __overlay__ {
                        spi0_cs1: spi0_cs1 {
                                pins = "PA21";
                                function = "gpio_out";
                                output-high;
                        };
                };
        };

        fragment@1 {
                target = <&spi0>;
                __overlay__ {
                        pinctrl-names = "default", "default";
                        pinctrl-1 = <&spi0_cs1>;
                        cs-gpios = <0>, <&pio 0 21 0>; /* PA21 */
                };
        };

};

 

sun8i-h3-spi-ads7846.dts

/dts-v1/;
/plugin/;

/ {
        compatible = "allwinner,sun8i-h3";

        fragment@0 {
                target = <&pio>;
                __overlay__ {
                        ads7846_pins: ads7846_pins {
                                pins= "PA2";
                                function = "irq";
                        };
                };
        };

        fragment@1 {
                target = <&spi0>;
                __overlay__ {
                        #address-cells = <1>;
                        #size-cells = <0>;
                        status = "okay";

                        ads7846@0 {
                                compatible = "ti,ads7846";
                                reg = <1>; /* Chip Select 0 */
                                status = "okay";
                                pinctrl-names = "default";
                                pinctrl-0 = <&ads7846_pins>;
                                spi-max-frequency = <500000>;
                                interrupt-parent = <&pio>;
                                interrupts = <0 2 2>; /* PA7 IRQ_TYPE_EDGE_FALLING */
                                pendown-gpio = <&pio 0 2 0>; /* PA7 */

                                /* driver defaults, optional */
                                ti,x-min = /bits/ 16 <176>;
                                ti,y-min = /bits/ 16 <300>;
                                ti,x-max = /bits/ 16 <3913>;
                                ti,y-max = /bits/ 16 <3947>;
                                ti,pressure-min = /bits/ 16 <0>;
                                ti,pressure-max = /bits/ 16 <255>;
                                ti,x-plate-ohms = /bits/ 16 <180>;
                                ti,debounce_max = /bits/ 16 <15000>;
                                ti,debounce_tol = /bits/ 16 <65535>;
                                ti,debounce_rep = /bits/ 16 <100>;
                                ti,vref-delay-usecs = /bits/ 16 <450>;
                                ti,keep_vref_on =  <1>;
                        };
                };
        };
};

ds1307.dts

/dts-v1/;
/plugin/;

/ {
    compatible = "brcm,bcm2708";

    fragment@0 {
            target = <&i2c0>;

            __overlay__ {
                    #address-cells = <1>;
                    #size-cells = <0>;
                    status = "okay";

                    ds1307@68 {
                            compatible = "ds1307";
                            reg = <0x68>;
                            status = "okay";
                    };
            };
      };
};

 

 

Also I have used mcp3204.py python script for test from here https://gist.github.com/yoggy/7096133

 

 

 

 

Link to comment
Share on other sites

@zador.blood.stained, I'm pretty sure you are not considering me as newbie on both Armbian and DT ...

But I feel like a newbie since I've never use spi-add-cs1 until now !

I've designed a board with 7 RS485 buses, 3 buses on plain /dev/ttyS* provided on header along with 4 buses provided by 2 sc16is752 and shown as /dev/ttySC*.

The first sc16is752 works well on SPI0-cs0, but the second doesn't work, and troubleshooting reveal me that PA21 never been initialized and left in floating state, although spi-add-cs1 is loaded properly ...

Doing search into /driver/spi/ kernel folder reveal to me, if I understood, that drivers/spi/spi-sun*i doesn't handle any things related to "cs-gpios", so those DT doesn't handle this entry, like other drivers do.

I'm wrong thinking that compatible = "allwinner,sun8i-h3-spi" will never support CS1 until maintainer add the proper code for it ?

Why people above got some success ?
Is the only solution is to switch compatible to "allwinner,spi-gpios", so bitbanging ?

 

That is a bad week for me on that project, since I've faced similar issue with the 3 first RS-485 : compatible = "snps,dw-apb-uart" doesn't support "linux,rs485-enabled-at-boot-time;", so Iǘe now only 2 buses out of 7 ...

I've found this recent patch https://lkml.org/lkml/2018/6/1/344 but trying to use it, I got a kernel crash on interrupts ... :(

 

Thanks in advance for any of your advices,

Martin

 

Link to comment
Share on other sites

7 hours ago, martinayotte said:

Doing search into /driver/spi/ kernel folder reveal to me, if I understood, that drivers/spi/spi-sun*i doesn't handle any things related to "cs-gpios", so those DT doesn't handle this entry, like other drivers do.

"cs-gpios" are handled by the spi-bus core: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/Documentation/devicetree/bindings/spi/spi-bus.txt

 

7 hours ago, martinayotte said:

Why people above got some success ?

Last time I tested it (maybe a year ago?) it worked for me (and I tested it on H3 and H5 if I remember correctly). Please keep in mind that current overlays may be broken (you should at least try this branch if you are using anything kernel newer than 4.14).

 

7 hours ago, martinayotte said:

The first sc16is752 works well on SPI0-cs0, but the second doesn't work, and troubleshooting reveal me that PA21 never been initialized and left in floating state, although spi-add-cs1 is loaded properly ...

Is there anything suspicious in dmesg? I would suggest trying CS1 with dual spidev configuration as it is easier to debug.

 

8 hours ago, martinayotte said:

That is a bad week for me on that project, since I've faced similar issue with the 3 first RS-485 : compatible = "snps,dw-apb-uart" doesn't support "linux,rs485-enabled-at-boot-time;", so Iǘe now only 2 buses out of 7 ...

Out of 7? Are we talking about H3/H5 or A20?

Link to comment
Share on other sites

4 hours ago, zador.blood.stained said:

"cs-gpios" are handled by the spi-bus core

Yes, I know, but the array containing those are initialized as member spi->cs_gpio, but not all drivers are using it, which is confirmed by grepping devm_gpio_request.

4 hours ago, zador.blood.stained said:

Please keep in mind that current overlays may be broken

It seems to work fine on the overlay itself, status is "applied", pins are present in DT.

4 hours ago, zador.blood.stained said:

I would suggest trying CS1 with dual spidev configuration as it is easier to debug

Yes, I will do, and this will give me the opportunity to learn more about those gpios handling, but in long term, since sc16is7xx driver sit on top of plain SPIs, not on top of SPIDEVs, I think I will have to create a patch for sc16is7xx driver itself.

EDIT : With SPIDEV, the CS1 is initialized properly, so I need to find out why it is not when not using SPIDEV, but plain SPI. That is why no-one faced the issue, since people are always using spidev.

 

4 hours ago, zador.blood.stained said:

Out of 7? Are we talking about H3/H5 or A20?

H3 ! only 3 first port directly, the 4 others are coming from those 2x sc16is7xx chips. If at least I get the SPIx_CS working, maybe I will redesign the board and use exclusively 4x sc16is7xx chip and get 8 ports from them.

 

Link to comment
Share on other sites

1 hour ago, martinayotte said:

Yes, I know, but the array containing those are initialized as member spi->cs_gpio, but not all drivers are using it, which is confirmed by grepping devm_gpio_request.

Again, it should be controlled by the bus, check the spi_set_cs function here. First it checks for valid GPIO properties, and if it doesn't look like a valid one, it falls back to the HW CS if the master controller provides a function pointer for setting one.

 

1 hour ago, martinayotte said:

EDIT : With SPIDEV, the CS1 is initialized properly, so I need to find out why it is not when not using SPIDEV, but plain SPI. That is why no-one faced the issue, since people are always using spidev.

As I understand it, CS handling is done entirely by the bus master subsystem so slave drivers should not know anything about it, as long as DT sets correct "reg" properties for the SPI slave nodes.

Link to comment
Share on other sites

26 minutes ago, zador.blood.stained said:

As I understand it, CS handling is done entirely by the bus master subsystem

I'm currently building new kernel with some traces added, because I feel like some drivers are doing that but some others don't, bypassing with their own set_cs, which seems to be the case for sun6i, traces will confirm ...

Link to comment
Share on other sites

@zador.blood.stained After adding traces, I figured out that set_cs functions were properly called. But after digging, I found where the "spaghetti" is located :

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/drivers/spi/spi.c#n2805

Most of the drivers, such atmel/stm32/omap initialise another callback call setup() in which handling the gpio_request() and gpio_direction_output(), but both the spi-sun4i and spi-sun6i doen't provide such setup() function.

I will try to add it myself, but in longer terms, I think I should ask Maxim to do it, since he is the maintainer ...

 

Link to comment
Share on other sites

Is there any news on this?

I'm seeing the same with an Infineon TPM Module for the Raspberrypi -- I'm using it on the Orange-Pi and by default it is wired for the second SPI Chip select. If I rewire for the first, it works fine. But so far I was unsuccessful using the second chip-select as follows (see below). Note that I'm using a mainline kernel (4.20.5 gregkh stable series), so it may well be that armbian has a patch that didn't make it to mainline yet?

 

&pio {
        spi1_cs1: spi1_cs1 {
                pins = "PA10";
                function = "gpio_out";
                output-high;
        };
};

&spi1 {
        status = "okay";
        pinctrl-names = "default", "default";
        pinctrl-1 = <&spi1_cs1>;
        cs-gpios = <0>, <&pio 0 10 GPIO_ACTIVE_HIGH> /* PA10 */;

        slb9670: slb9670@1 {
                compatible = "infineon,slb9670";
                reg = <1>;
                spi-max-frequency = <1000000>;
                status = "okay";
        };
};

Edited by runtux
forgot something
Link to comment
Share on other sites

I think the pinctrl is right, see above in my initial quote of the &pio, I'm adding a second pinctrl for the chipselect 1 (the one I want to add).

The full dtb when disassembling looks as follows:

 

                spi@1c69000 {
                        compatible = "allwinner,sun8i-h3-spi";
                        reg = < 0x1c69000 0x1000 >;
                        interrupts = < 0x00 0x42 0x04 >;
                        clocks = < 0x03 0x1f 0x03 0x53 >;
                        clock-names = "ahb\0mod";
                        dmas = < 0x14 0x18 0x14 0x18 >;
                        dma-names = "rx\0tx";
                        pinctrl-names = "default\0default";
                        pinctrl-0 = < 0x16 >;
                        resets = < 0x03 0x10 >;
                        status = "okay";
                        #address-cells = < 0x01 >;
                        #size-cells = < 0x00 >;
                        pinctrl-1 = < 0x17 >;
                        cs-gpios = < 0x00 0x0a 0x00 0x0a 0x00 >;

                        slb9670@0 {
                                compatible = "infineon,slb9670";
                                reg = < 0x00 >;
                                spi-max-frequency = < 0xf4240 >;
                                status = "okay";
                        };

                };

 

Note that this has two pinctrl specs, the 0th is the default one:

 

                        spi1 {
                                pins = "PA15\0PA16\0PA14\0PA13";
                                function = "spi1";
                                phandle = < 0x16 >;
                        };

 

while the 1st is the one I added:

 

                        spi1_cs1 {
                                pins = "PA10";
                                function = "gpio_out";
                                output-high;
                                phandle = < 0x17 >;
                        };

 

When grepping for spi during boot I'm only getting the message of the NOR flash on the spi0 bus, nothing for spi1.

If I use cs0 for my TPM module (I now have one module soldered for cs0, one for cs1) *and* load the driver by hand (it doesn't autoload) I'm getting:

 

root@sun8i:~# modprobe tpm_tis_spi                                              
[   48.731922] tpm_tis_spi spi1.0: 2.0 TPM (device-id 0x1B, rev-id 16)          
[   48.741840] tpm tpm0: A TPM error (256) occurred attempting the self test    
[   48.748632] tpm tpm0: starting up the TPM manually                           
[   48.767135] tpm tpm0: A TPM error (2314) occurred attempting the self test 

 

dmesg | grep spi                                                                
[    0.889509] m25p80 spi0.0: mx25l1606e (2048 Kbytes)                          
[   48.731922] tpm_tis_spi spi1.0: 2.0 TPM (device-id 0x1B, rev-id 16)          

 

Please note that I'm currently not using an armbian-provided kernel, so it may well be that armbian has a patch that I'm missing.

 

I'm also irritated by the fact that my cs-gpios that is specified as a tuple in the source:

 

 cs-gpios = <0>, <&pio 0 10 GPIO_ACTIVE_HIGH> /* PA10 */;

 

ends up as a five-integer sequence in the disassembled dts:

 

 cs-gpios = < 0x00 0x0a 0x00 0x0a 0x00 >;

Link to comment
Share on other sites

@martinayotte in your August 19, 2018 post you write that the sunxi spi drivers don't provide a proper setup function with the result that additional chip-selects are not initialized properly. Did you patch those drivers? If yes, are these patches only in armbian and can you maybe point me to them? So far I haven't found a problem in my cs config and it *does* work when using the built-in cs pin.

Link to comment
Share on other sites

1 hour ago, runtux said:

@martinayotte in your August 19, 2018 post you write that the sunxi spi drivers don't provide a proper setup function with the result that additional chip-selects are not initialized properly. Did you patch those drivers? If yes, are these patches only in armbian and can you maybe point me to them? So far I haven't found a problem in my cs config and it *does* work when using the built-in cs pin.

Oh ! You're right ! I didn't even commit that to Armbian, it still in my build tree uncommitted ...

 

Here is how it is look like :

 

diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index ec395a6..e3ced40 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -2805,6 +2807,19 @@ int spi_setup(struct spi_device *spi)
 	if (spi->controller->setup)
 		status = spi->controller->setup(spi);
 
+	if (gpio_is_valid(spi->cs_gpio)) {
+		dev_info(&spi->dev, "spi_setup / gpio_is_valid(%d) ... doing gpio_request ...\n", spi->cs_gpio);
+		int ret = gpio_request(spi->cs_gpio, dev_name(&spi->dev));
+		if (ret) {
+			dev_err(&spi->dev, "failed to request gpio\n");
+		}
+		else {
+			gpio_direction_output(spi->cs_gpio,
+				 !(spi->mode & SPI_CS_HIGH));
+			dev_info(&spi->dev, "spi_setup / gpio_direction_output(%d) done !\n", spi->cs_gpio);
+		}
+	}
+	
 	spi_set_cs(spi, false);
 
 	dev_dbg(&spi->dev, "setup mode %d, %s%s%s%s%u bits/w, %u Hz max --> %d\n",

Now committed into Armbian : https://github.com/armbian/build/commit/9f68190d348b24fcc3b47cee0d4d18f1b3cbef85

 

Link to comment
Share on other sites

@martinayotte thanks for the patch. I'm getting the same results with and without the patch. I've now set up measurement. The results measured (oscilloscope) are the same with and without the patch. So this might already be fixed in latest kernels. The reason why it doesn't work seems to be that the chipselect comes too early, at a time when the clock is still high (the default setup is that miso is sampled at the rising edge and/or the client should sample mosi at the rising edge). Now it seems that the tpm chip cannot handle the case where the cs is asserted before clock is low.

 

I've taken pictures:

this shows CS1 in yellow, clock in blue:

additional_cs1-5us.bmp

 

This shows the same for the (working) native cs0:

native-cs0.bmp

 

So it seems the driver is asserting cs too early in the process. I'll try a patch on the sunxi spi page and report back.

Link to comment
Share on other sites

I've applied the patch on the sunxi spidev page http://linux-sunxi.org/SPIdev (very much at the end, look for "HIGH on SCK line right before transfer") and this now never raises clock before beginning the transfer. The respecitive screenshot:

 

working_cs1.bmp

 

So you might want to check if armbian has that patch. It's working for me now, so my devicetree foo seems to have been ok all the time.

Link to comment
Share on other sites

Mike R9FT, I have huge doubts ... you claim to be able to make things work with Armbian_5.27.170521_Orangepione_Ubuntu_xenial_dev_4.11.1.7z , but you quote "overlays=spi-spidev" which is a kernel v3 specific option, and ignored by kernels v4 ...

 

After adding sun8i-h3-spi-ads7846.dts , my /dev/fb0 goes away.

 

orangepi zero

4.14.18-sunxi

user_overlays=myili9431

Link to comment
Share on other sites

Guest
This topic is now closed to further replies.
×
×
  • Create New...

Important Information

Terms of Use - Privacy Policy - Guidelines