Jump to content

spi0 CS1 held low when ads7846 is loaded


Taita

Recommended Posts

Armbianmonitor:

Heya,

 

Configuration ::

Friendlyarm NanoPi Neo (Allwinner H3)

Matrix TFT2.8 (https://www.friendlyarm.com/index.php?route=product/product&product_id=102)

Armbian Release: Bionic 5.8.y found here: https://www.armbian.com/nanopi-neo/

 

I have this st7789v-based display working on spi0.0 by utilising a custom overlay tft28.dts as below, but I cannot get the ads7846 touchscreen controller to use an additional gpio chip select (ie: spi0.1) because the ads7846 driver seems to be holding that additional cs line in a 'logic 0' state at zero volts.

 

I believe the hardware is not at fault because it works correctly using the Friendlyarm provided Xenial image (linux kernel 4.14) here: 

https://drive.google.com/drive/folders/1Fg81ce8ucTOMDWrlT-F_zwH0-UljRMsM

 

I can successfully register a second gpio chip select line for spi0 at the H3's gpio PA6 by using the custom cs1.dts below, which corresponds to pin12 of the Matrix 2.8TFT display's header. I can also load up a dummy 'spidev' device upon that additional chip select line which registers fine and is listed normally in dmesg as spi0.1. As long as I do not load up the ads7846 overlay, and use a dummy spidev at spi0.1 the PA6 gpio (ie: pin12 of the Matrix TFT28's header) stays logic high at 3.3volts which is expected idle operation for a spi chipselect line.

 

But whenever I try to enable the ads7846 driver instead of spidev, that additional CS line (ie: gpio PA6 = pin12 on the header) is being held permanently low at 0volts. Thus, the XPT2046 chip (ads7846 clone) does not work properly.

 

Any ideas on why this additional chipselect line (gpio PA6) is being held logic low at idle? Have I missed some assertion somewhere to make it idle at logic high (3.3v)? 

 

cs1.dts ::

/dts-v1/;
/plugin/;

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

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

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

};

 

tft28.dts ::

/dts-v1/;
/plugin/;
/ {
	compatible = "allwinner,sun8i-h3";
	
	fragment@0 {
		target = <&spi0>;
		__overlay__ {
				status = "okay";
		};
	};

	fragment@1 {
		target = <&spi0>;
			__overlay__ {
		
			pitft: pitft@0{
				compatible = "sitronix,st7789v";
				reg = <0>;
				status = "okay";
				spi-max-frequency = <50000000>;
				rotate = <90>;
				fps = <33>;
				buswidth = <8>;
				dc-gpios = <0x0b 0 1 0>;         /* PA1 */
				reset-gpios = <0x0b 6 11 0>; /* PG11 */
				led-gpios = <0x0b 0 0 0>;        /* PA0 */
				debug = <0x0>;
				};
			};
		};
	};

 

 

ads7846.dts ::

/dts-v1/;
/plugin/;
/ {
	compatible = "allwinner,sun4i-a10", "allwinner,sun7i-a20", "allwinner,sun8i-h3", "allwinner,sun50i-a64", "allwinner,sun50i-h5";
	
	fragment@0 {
		target = <&spi0>;
		__overlay__ {
				status = "okay";
		};
	};

	fragment@1 {
		target = <0x0b>;
		__overlay__ {
			ads7846_pins: ads7846_pins {
				pins= "PG9";
				function = "irq";
				};

		};
		
	};

	fragment@2 {
		target = <&spi0>;
			__overlay__ {
			
			ads7846@0 {
				pinctrl-names = "default";
				pinctrl-0 = <&ads7846_pins>;
				compatible = "ti,ads7846";
				reg = <0x1>;
				status = "okay";
				spi-max-frequency = <2000000>;
				interrupt-parent = <0x0b>;
				interrupts = <6 9 2>;   /* PG9 / EINT9 */
				pendown-gpio = <0x0b 6 9 0>;
				ti,swap-xy;
				ti,vref-delay-usecs = <1000>;
				ti,x-min = /bits/ 16 <100>;
				ti,x-max = /bits/ 16 <0xfff>;
				ti,y-min = /bits/ 16 <100>;
				ti,y-max = /bits/ 16 <0xfff>;
				ti,vref-mv = <3300>;
				ti,x-plate-ohms = /bits/ 16 <256>;
				ti,penirq-recheck-delay-usecs = <10>;
				ti,settle-delay-usec = /bits/ 16 <100>;
				ti,keep-vref-on = <1>;
				ti,pressure-max = /bits/ 16 <0xfff>;
				ti,debounce-max = <10>;
				ti,debounce-tol = <30>;
				ti,debounce-rep = <1>; 
				};
			};
		};
	};

 

 

/boot/armbianEnv.txt ::

 

verbosity=1
bootlogo=false
console=serial
disp_mode=1920x1080p60
overlay_prefix=sun8i-h3
overlays=usbhost1 usbhost2
rootdev=UUID=7563442c-8c5f-41d1-ae68-eb9ab2f39452
rootfstype=ext4
user_overlays= cs1 tft28 ts
#user_overlays= cs1 tft28 spidev
#param_spidev_spi_bus=0
#param_spidev_spi_cs=1
usbstoragequirks=0x2537:0x1066:u,0x2537:0x1068:u

 

 

Output of dmesg | grep spi

 

root@nanopineo:~# dmesg | grep spi
[    9.606195] ads7846 spi0.1: supply vcc not found, using dummy regulator
[    9.612769] fb_st7789v spi0.0: fbtft_property_value: buswidth = 8
[    9.612786] fb_st7789v spi0.0: fbtft_property_value: debug = 0
[    9.612794] fb_st7789v spi0.0: fbtft_property_value: rotate = 90
[    9.612801] fb_st7789v spi0.0: fbtft_property_value: fps = 33
[    9.628147] ads7846 spi0.1: touchscreen, irq 102
[    9.628861] input: ADS7846 Touchscreen as /devices/platform/soc/1c68000.spi/spi_master/spi0/spi0.1/input/input1
[    9.822379] graphics fb0: fb_st7789v frame buffer, 320x240, 150 KiB video memory, 4 KiB buffer memory, fps=35, spi0.0 at 50 MHz

 

Link to comment
Share on other sites

Hi Coby, I can't even get evtest to register any input, although the ads7846 is triggering udev to register an input device (event 1).

 

Measuringthe spi0.1 cs GPIO pin during startup shows it goes high momentarily after UBoot kicks off the kernel, then it drops low as soon as the ads7846 kernel module is loaded.

Link to comment
Share on other sites

Okay I have made some progress, I think. Still no data coming from /dev/input/event1 though. 

 

Working theory ATM is that the issue is here in ads7846.c ::

 

/* leave chip selected when we're done, for quicker re-select? */
#if     0
#define CS_CHANGE(xfer) ((xfer).cs_change = 1)
#else
#define CS_CHANGE(xfer) ((xfer).cs_change = 0)
#endif
 

... which made me think that the driver was keeping the CS line permanently active (ie: low).  Assuming that the code authors presumed that ads7846 silicon would inhabit a spi bus all to itself. So I swapped them to make cs_change = 1 and rebuilt the module; now that CS line is now kept high when the screen is not touched, and pulses low when the system recieves interrupt (extected behaviour).

 

No activity can be seen via evtest though. Time to get the oscilloscope out.

Link to comment
Share on other sites

** SOLVED **

 

The problem is caused by a change made somewhere upstream in mainline which causes any non-native chipselect lines (ie: assigned via GPIO) to be inverted through gpiolib. This causes such CS lines to default to the behaviour of active-high once it reaches the physical layer - at least for the ads7846 driver. I don't know exactly where this change was committed or why, but this should not be the default behaviour...it breaks drivers FFS!

 

The solution would be to either:

a) Re-write the ads7846.c driver to re-invert the CS behavior at the driver level (not gonna happen...not tonight anyways) 

b) Use the original ads7846.ko module (don't bother re-compiling like I tried above) and insert this 'legacy' line into the device tree fragment for the ads7846::

 

spi-cs-high;

 

...which I found referenced here in spi.c where it parses the dt for that driver and inverts the CS line:

https://elixir.bootlin.com/linux/v5.8.11/source/drivers/spi/spi.c#L1900

 

The net effect is that the device-tree "spi-cs-high;" inverts the CS logic for that slave device, which then gets re-inverted back to normality via gpiolib.  The reasons behind the upstream commit that caused this error are not clear or logical (go searching for it if you could be bothered) but CS active high is *very* rare,  and problems shouldn't have to be solved by putting a 'legacy' device tree binding to fix a 'mainline' commit.  Oh well, that's Linux for ya...we cannot complain whilst standing on the shoulders of giants.

 

Happy poking :)

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
×
×
  • Create New...

Important Information

Terms of Use - Privacy Policy - Guidelines