aBUGSworstnightmare
Posts: 9277
Joined: Tue Jun 30, 2015 1:35 pm

Replacing SPI control signals by GPIO expander fails

Mon Nov 27, 2023 7:03 pm

In order to free some of the GPIO40 signals I'm currently trying to replace some SPI display control signals by GPIO expander.
I'm using a PCA9685 and have PWM GPIO module enabled in the kernel which should allow me to use it's outputs as PWM and GPIO.

Sadly that's not working as expected! RESET is working fine, DC is not working as expected.
My DUT is a Pi4, display + touch are on SPI0.

That's what my logs look most of the time - display is non-working though!
https://paste.debian.net/hidden/df1aad99/

Also found below from the logs (only once so far) which looks odd:

Code: Select all

[    9.119619] leds-gpio controls@0: Failed to create device link (0x180) with 1-0040
[    9.119671] leds-gpio controls@0: Failed to create device link (0x180) with 1-0040
[    9.119700] leds-gpio controls@0: Failed to create device link (0x180) with 1-0040
[    9.119728] leds-gpio controls@0: Failed to create device link (0x180) with 1-0040
[    9.119755] leds-gpio controls@0: Failed to create device link (0x180) with 1-0040
[    9.119782] leds-gpio controls@0: Failed to create device link (0x180) with 1-0040
[    9.119807] leds-gpio controls@0: Failed to create device link (0x180) with 1-0040
[    9.119834] leds_pwm leds@0: Failed to create device link (0x180) with 1-0040
[    9.119860] leds_pwm leds@0: Failed to create device link (0x180) with 1-0040
[    9.147075] leds_pwm leds@0: Failed to create device link (0x180) with 1-0040
[    9.149168] pwm-backlight backlight_spi1: supply power not found, using dummy regulator
[    9.152487] pwm-backlight backlight_spi0: supply power not found, using dummy regulator
[    9.156206] panel-mipi-dbi-spi spi0.0: supply power not found, using dummy regulator
[    9.164751] [drm] Initialized panel-mipi-dbi 1.0.0 20220103 for spi0.0 on minor 2
The device tree overlay in question can be found below. Routing 'dc-gpios' to a GPIO40 (i.e. 26) let's the display start working perfectly fine.

Code: Select all

/*
 * mipi-dbi-spi0-no-miso-pca-overlay.dts
 */

#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/leds/common.h>

/dts-v1/;
/plugin/;

/ {
	compatible = "brcm,bcm2835";

	fragment@0 {
		target = <&spi0>;
		__overlay__ {
			status = "okay";
		};
	};

	fragment@1 {
		target = <&spidev0>;
		__overlay__ {
			status = "disabled";
		};
	};

	fragment@2 {
		target = <&spidev1>;
		__overlay__ {
			status = "disabled";
		};
	};

	fragment@3 {
		target = <&gpio>;
		__overlay__ {
			panel_pins: panel_pins {
				brcm,pins = <17>;
				brcm,function = <0>; /* in */
			};
		};
	};

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

			pca: pca@40 {
				compatible = "nxp,pca9685-pwm";
				#pwm-cells = <2>;
				gpio-controller;
				#gpio-cells = <2>;
				reg = <0x40>;
				status = "okay";

				gpio-line-names = "PCA_PWM0",
				  "PCA_PWM1",
				  "PCA_CS0_TFT",
				  "PCA_CS1_TP",
				  "PCA_RST",
				  "PCA_DC",
				  "PCA_AUX0",
				  "PCA_AUX1",
				  "PCA_AUX2",
				  "PCA_AUX3",
				  "PCA_AUX4",
				  "PCA_BL0_EN",
				  "PCA_BL1_EN",
				  "PCA_STATE0",
				  "PCA_STATE1",
				  "PCA_STATE2";
			};
		};
	};

	fragment@51 {
		target-path = "/";
		__overlay__ {
			backlight_spi0: backlight_spi0 {
				compatible = "pwm-backlight";
				brightness-levels = <0 4095>;
				num-interpolated-steps = <4096>;
				default-brightness-level = <4096>;
				pwms = <&pca 0 5000000>;
				// enable signal controlled by PCA9586-#11
				enable-gpios = <&pca 11 0>;
				status = "okay";
			};
				
			backlight_spi1: backlight_spi1 {
				compatible = "pwm-backlight";
				brightness-levels = <0 4095>;
				num-interpolated-steps = <4096>;
				default-brightness-level = <4096>;
				pwms = <&pca 1 5000000>;
				// enable signal controlled by PCA9586-#12
				enable-gpios = <&pca 12 0>;
				status = "okay";
			};

			controls: controls@0 {
				compatible = "gpio-leds";
				status = "okay";

				aux0: aux0@1 {
					label = "aux0";
					linux,default-trigger = "none";					
					gpios = <&pca 6 0>;
				};

				aux1: aux1@1 {
					label = "aux1";
					linux,default-trigger = "none";
					gpios = <&pca 7 0>;
				};

				aux2: aux2@1 {
					label = "aux2";
					linux,default-trigger = "none";
					gpios = <&pca 8 0>;
				};

				aux3: aux3@1 {
					label = "aux3";
					linux,default-trigger = "none";
					gpios = <&pca 9 0>;
				};

				aux4: aux4@1 {
					label = "aux4";
					linux,default-trigger = "none";
					gpios = <&pca 10 0>;
				};																									
			};

			leds: leds@0 {
				compatible = "pwm-leds";
				status = "okay";

				// available PWM range for LED 0 - 255
				state0: state0@13 {
					label = "state0";
					pwms = <&pca 13 5000000>;
					pwm-names = "state0";
				};

				state1: state1@14 {
					label = "state1";
					pwms = <&pca 14 5000000>;
					pwm-names = "state1";
				};

				state2: state2@15 {
					label = "state2";
					pwms = <&pca 15 5000000>;
					pwm-names = "state2";
				};
			};
		};
	};

	fragment@52 {
		target-path = "/";
		__overlay__ {
				pwm_gpio: pwm_gpio@0 {
					compatible = "pwm-gpio";
					reg = <0x0>;
					gpio-controller;
					#gpio-cells = <2>;

					pwms =  <&pca 2 5000000>, 
							<&pca 3 5000000>,
							<&pca 4 5000000>,
							<&pca 5 5000000>,
							<&pca 6 5000000>,
							<&pca 7 5000000>,
							<&pca 8 5000000>,
							<&pca 9 5000000>,
							<&pca 10 5000000>,
							<&pca 11 5000000>,
							<&pca 12 5000000>;
					pwm-names = "pca_cs0_tft", "pca_cs1_tp",
							"pca_rst",
							"pca_dc",
							"aux0", "aux1", "aux2", "aux3", "aux4",
							"bl0_en", "bl1_en";

					status = "okay";
				};											
		};
	};

	panel_fragment: fragment@100 {
		target = <&spi0>;
		__overlay__ {
			/* needed to avoid dtc warning */
			#address-cells = <1>;
			#size-cells = <0>;

			status = "okay";

			panel: panel@0 {
				compatible = "panel", "panel-mipi-dbi-spi";
				reg = <0>;
				spi-max-frequency = <32000000>;

				width-mm = <0>;
				height-mm = <0>;
                
                reset-gpios = <&pca 4 GPIO_ACTIVE_HIGH>;
                dc-gpios = <&pca 5 GPIO_ACTIVE_HIGH>;
                
				timing: panel-timing {
					hactive = <320>;
					vactive = <240>;
					hback-porch = <0>;
					vback-porch = <0>;

					clock-frequency = <0>;
					hfront-porch = <0>;
					hsync-len = <0>;
					vfront-porch = <0>;
					vsync-len = <0>;
				};
			};
			
			panel_ts: spanel_ts@1 {
				compatible = "ti,ads7846";
				reg = <1>;

				spi-max-frequency = <2000000>;
				interrupts = <5 2>; /* high-to-low edge triggered */
				interrupt-parent = <&gpio>;
				pendown-gpio = <&gpio 5 0>;
				//ti,swap-xy;
				ti,x-plate-ohms = /bits/ 16 <100>;
				ti,pressure-max = /bits/ 16 <255>;
			};
		};
	};

	fragment@101 {
		target = <&panel>;
		__dormant__  {
			backlight = <&backlight_spi0>;
		};
	};
	__overrides__ {
		compatible    = <&panel>, "compatible";

		speed         = <&panel>, "spi-max-frequency:0";
		cpha          = <&panel>, "spi-cpha?";
		cpol          = <&panel>, "spi-cpol?";

		width         = <&timing>, "hactive:0";
		height        = <&timing>, "vactive:0";
		x-offset      = <&timing>, "hback-porch:0";
		y-offset      = <&timing>, "vback-porch:0";
		clock-frequency = <&timing>, "clock-frequency:0";

		width-mm      = <&panel>, "width-mm:0";
		height-mm     = <&panel>, "height-mm:0";

		/* optional gpios */
		reset-gpio    = <&panel>, "reset-gpios:0=", <&gpio>,
				<&panel>, "reset-gpios:4",
				<&panel>, "reset-gpios:8=0"; /* GPIO_ACTIVE_HIGH */
		dc-gpio       = <&panel>, "dc-gpios:0=", <&gpio>,
				<&panel>, "dc-gpios:4",
				<&panel>, "dc-gpios:8=0"; /* GPIO_ACTIVE_HIGH */

		backlight-pwm         = <0>, "+101";
		backlight-def-brightness = <&backlight_spi0>, "default-brightness-level:0";
	};
};

Code: Select all

pi@bookworm:~ $ gpioinfo
gpiochip0 - 58 lines:
	line   0:     "ID_SDA"       unused   input  active-high 
	line   1:     "ID_SCL"       unused   input  active-high 
	line   2:       "SDA1"       unused   input  active-high 
	line   3:       "SCL1"       unused   input  active-high 
	line   4:  "GPIO_GCLK"       unused   input  active-high 
	line   5:      "GPIO5" "ads7846_pendown" input active-high [used]
	line   6:      "GPIO6"       unused   input  active-high 
	line   7:  "SPI_CE1_N"   "spi0 CS1"  output   active-low [used]
	line   8:  "SPI_CE0_N"   "spi0 CS0"  output   active-low [used]
	line   9:   "SPI_MISO"       unused   input  active-high 
	line  10:   "SPI_MOSI"       unused   input  active-high 
	line  11:   "SPI_SCLK"       unused   input  active-high 
	line  12:     "GPIO12"       unused   input  active-high 
	line  13:     "GPIO13"       unused   input  active-high 
	line  14:       "TXD1"       unused   input  active-high 
	line  15:       "RXD1"       unused   input  active-high 
	line  16:     "GPIO16"       unused   input  active-high 
	line  17:     "GPIO17"       unused   input  active-high 
	line  18:     "GPIO18"       unused   input  active-high 
	line  19:     "GPIO19"       unused   input  active-high 
	line  20:     "GPIO20"       unused   input  active-high 
	line  21:     "GPIO21"       unused   input  active-high 
	line  22:     "GPIO22"       unused   input  active-high 
	line  23:     "GPIO23"       unused   input  active-high 
	line  24:     "GPIO24"       unused   input  active-high 
	line  25:     "GPIO25"       unused   input  active-high 
	line  26:     "GPIO26"       unused   input  active-high 
	line  27:     "GPIO27"       unused   input  active-high 
	line  28: "RGMII_MDIO"       unused   input  active-high 
	line  29:  "RGMIO_MDC"       unused   input  active-high 
	line  30:       "CTS0"       unused   input  active-high 
	line  31:       "RTS0"       unused   input  active-high 
	line  32:       "TXD0"       unused   input  active-high 
	line  33:       "RXD0"       unused   input  active-high 
	line  34:    "SD1_CLK"       unused   input  active-high 
	line  35:    "SD1_CMD"       unused   input  active-high 
	line  36:  "SD1_DATA0"       unused   input  active-high 
	line  37:  "SD1_DATA1"       unused   input  active-high 
	line  38:  "SD1_DATA2"       unused   input  active-high 
	line  39:  "SD1_DATA3"       unused   input  active-high 
	line  40:  "PWM0_MISO"       unused   input  active-high 
	line  41:  "PWM1_MOSI"       unused   input  active-high 
	line  42: "STATUS_LED_G_CLK" "ACT" output active-high [used]
	line  43: "SPIFLASH_CE_N" unused input active-high 
	line  44:       "SDA0"       unused   input  active-high 
	line  45:       "SCL0"       unused   input  active-high 
	line  46: "RGMII_RXCLK" unused input active-high 
	line  47: "RGMII_RXCTL" unused input active-high 
	line  48: "RGMII_RXD0"       unused   input  active-high 
	line  49: "RGMII_RXD1"       unused   input  active-high 
	line  50: "RGMII_RXD2"       unused   input  active-high 
	line  51: "RGMII_RXD3"       unused   input  active-high 
	line  52: "RGMII_TXCLK" unused input active-high 
	line  53: "RGMII_TXCTL" unused input active-high 
	line  54: "RGMII_TXD0"       unused   input  active-high 
	line  55: "RGMII_TXD1"       unused   input  active-high 
	line  56: "RGMII_TXD2"       unused   input  active-high 
	line  57: "RGMII_TXD3"       unused   input  active-high 
gpiochip1 - 8 lines:
	line   0:      "BT_ON"   "shutdown"  output  active-high [used]
	line   1:      "WL_ON"       unused  output  active-high 
	line   2: "PWR_LED_OFF" "PWR" output active-low [used]
	line   3: "GLOBAL_RESET" unused output active-high 
	line   4: "VDD_SD_IO_SEL" "vdd-sd-io" output active-high [used]
	line   5:   "CAM_GPIO" "cam1_regulator" output active-high [used]
	line   6:  "SD_PWR_ON" "regulator-sd-vcc" output active-high [used]
	line   7:    "SD_OC_N"       unused   input  active-high 
gpiochip2 - 16 lines:
	line   0:   "PCA_PWM0"       unused  output  active-high 
	line   1:   "PCA_PWM1"       unused  output  active-high 
	line   2: "PCA_CS0_TFT" unused output active-high 
	line   3: "PCA_CS1_TP"       unused  output  active-high 
	line   4:    "PCA_RST"      "reset"  output  active-high [used]
	line   5:     "PCA_DC"         "dc"  output  active-high [used]
	line   6:   "PCA_AUX0"       "aux0"  output  active-high [used]
	line   7:   "PCA_AUX1"       "aux1"  output  active-high [used]
	line   8:   "PCA_AUX2"       "aux2"  output  active-high [used]
	line   9:   "PCA_AUX3"       "aux3"  output  active-high [used]
	line  10:   "PCA_AUX4"       "aux4"  output  active-high [used]
	line  11: "PCA_BL0_EN"     "enable"  output  active-high [used]
	line  12: "PCA_BL1_EN"     "enable"  output  active-high [used]
	line  13: "PCA_STATE0"       unused  output  active-high 
	line  14: "PCA_STATE1"       unused  output  active-high 
	line  15: "PCA_STATE2"       unused  output  active-high 
pi@bookworm:~ $ sudo cat /sys/kernel/debug/pwm
i2c/1-0040, 17 PWM devices
 pwm-0   (backlight_spi0      ): requested enabled period: 5000000 ns duty: 3124542 ns polarity: normal
 pwm-1   (backlight_spi1      ): requested enabled period: 5000000 ns duty: 0 ns polarity: normal
 pwm-2   ((null)              ): period: 0 ns duty: 0 ns polarity: normal
 pwm-3   ((null)              ): period: 0 ns duty: 0 ns polarity: normal
 pwm-4   ((null)              ): period: 0 ns duty: 0 ns polarity: normal
 pwm-5   ((null)              ): period: 0 ns duty: 0 ns polarity: normal
 pwm-6   ((null)              ): period: 0 ns duty: 0 ns polarity: normal
 pwm-7   ((null)              ): period: 0 ns duty: 0 ns polarity: normal
 pwm-8   ((null)              ): period: 0 ns duty: 0 ns polarity: normal
 pwm-9   ((null)              ): period: 0 ns duty: 0 ns polarity: normal
 pwm-10  ((null)              ): period: 0 ns duty: 0 ns polarity: normal
 pwm-11  ((null)              ): period: 0 ns duty: 0 ns polarity: normal
 pwm-12  ((null)              ): period: 0 ns duty: 0 ns polarity: normal
 pwm-13  (state0              ): requested period: 5000000 ns duty: 0 ns polarity: normal
 pwm-14  (state1              ): requested period: 5000000 ns duty: 0 ns polarity: normal
 pwm-15  (state2              ): requested period: 5000000 ns duty: 0 ns polarity: normal
 pwm-16  ((null)              ): period: 0 ns duty: 0 ns polarity: normal
pi@bookworm:~ $ gpiodetect
gpiochip0 [pinctrl-bcm2711] (58 lines)
gpiochip1 [raspberrypi-exp-gpio] (8 lines)
gpiochip2 [1-0040] (16 lines)
pi@bookworm:~ $ ls /sys/bus/i2c/drivers
dummy  pca9685-pwm  stmpe-i2c

Code: Select all

 0: ip    pu | hi // ID_SDA/GPIO0 = input
 1: ip    pu | hi // ID_SCL/GPIO1 = input
 2: a0    pu | hi // SDA1/GPIO2 = SDA1
 3: a0    pu | hi // SCL1/GPIO3 = SCL1
 4: ip    pu | hi // GPIO_GCLK/GPIO4 = input
 5: ip    pu | hi // GPIO5 = input
 6: ip    pu | hi // GPIO6 = input
 7: op -- pu | hi // SPI_CE1_N/GPIO7 = output
 8: op -- pu | hi // SPI_CE0_N/GPIO8 = output
 9: a0    pd | lo // SPI_MISO/GPIO9 = SPI0_MISO
10: a0    pd | lo // SPI_MOSI/GPIO10 = SPI0_MOSI
11: a0    pd | hi // SPI_SCLK/GPIO11 = SPI0_SCLK
12: ip    pd | lo // GPIO12 = input
13: ip    pd | lo // GPIO13 = input
14: ip    pn | hi // TXD1/GPIO14 = input
15: ip    pu | hi // RXD1/GPIO15 = input
16: ip    pd | lo // GPIO16 = input
17: ip    pd | lo // GPIO17 = input
18: ip    pd | lo // GPIO18 = input
19: ip    pd | lo // GPIO19 = input
20: ip    pd | lo // GPIO20 = input
21: ip    pd | lo // GPIO21 = input
22: ip    pd | lo // GPIO22 = input
23: ip    pd | lo // GPIO23 = input
24: ip    pd | lo // GPIO24 = input
25: ip    pd | lo // GPIO25 = input
26: ip    pd | lo // GPIO26 = input
27: ip    pd | lo // GPIO27 = input
28: a5    pu | hi // RGMII_MDIO/GPIO28 = RGMII_MDIO
29: a5    pd | lo // RGMIO_MDC/GPIO29 = RGMII_MDC
30: a3    pu | lo // CTS0/GPIO30 = CTS0
31: a3    pn | lo // RTS0/GPIO31 = RTS0
32: a3    pn | hi // TXD0/GPIO32 = TXD0
33: a3    pu | hi // RXD0/GPIO33 = RXD0
34: a3    pn | hi // SD1_CLK/GPIO34 = SD1_CLK
35: a3    pu | hi // SD1_CMD/GPIO35 = SD1_CMD
36: a3    pu | hi // SD1_DATA0/GPIO36 = SD1_DAT0
37: a3    pu | hi // SD1_DATA1/GPIO37 = SD1_DAT1
38: a3    pu | hi // SD1_DATA2/GPIO38 = SD1_DAT2
39: a3    pu | hi // SD1_DATA3/GPIO39 = SD1_DAT3
40: a0    pn | lo // PWM0_MISO/GPIO40 = PWM1_0
41: a0    pn | lo // PWM1_MOSI/GPIO41 = PWM1_1
42: op -- pu | lo // STATUS_LED_G_CLK/GPIO42 = output
43: ip    pu | hi // SPIFLASH_CE_N/GPIO43 = input
44: ip    pu | hi // SDA0/GPIO44 = input
45: ip    pu | hi // SCL0/GPIO45 = input
46: ip    pu | lo // RGMII_RXCLK/GPIO46 = input
47: ip    pu | lo // RGMII_RXCTL/GPIO47 = input
48: ip    pd | lo // RGMII_RXD0/GPIO48 = input
49: ip    pd | lo // RGMII_RXD1/GPIO49 = input
50: ip    pd | lo // RGMII_RXD2/GPIO50 = input
51: ip    pd | lo // RGMII_RXD3/GPIO51 = input
52: ip    pd | lo // RGMII_TXCLK/GPIO52 = input
53: ip    pd | lo // RGMII_TXCTL/GPIO53 = input
data from my config.txt for calling the overlay:

Code: Select all

# 2.8in QVGA
dtoverlay=mipi-dbi-spi0-no-miso-pca,speed=32000000
dtparam=compatible=wavesku18366\0panel-mipi-dbi-spi
dtparam=cpha,cpol
dtparam=width=320,height=240,width-mm=57,height-mm=43
#dtparam=dc-gpio=26
dtparam=backlight-pwm
Any idea what is wrong with the overlay?

6by9
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 15880
Joined: Wed Dec 04, 2013 11:27 am
Location: ZZ9 Plural Z Alpha, aka just outside Cambridge.

Re: Replacing SPI control signals by GPIO expander fails

Tue Nov 28, 2023 4:27 pm

Initial guess would be timing in setting PCA9685 outputs.

Do note that you should be able to use PCA9685 directly as either PWM or GPIO outputs, making "pwm-gpio" redundant in this case.

That may well be your problem - you've used

Code: Select all

                reset-gpios = <&pca 4 GPIO_ACTIVE_HIGH>;
                dc-gpios = <&pca 5 GPIO_ACTIVE_HIGH>;
to go direct to the pca, but pwm_gpio is also registered to take pca pwm outputs 2-12.
As it's a gpiod_get_optional call from panel-mipi-dbi, it's plausible that it's failed (because the GPIO is busy), and that has significant side effects within the driver. reset is also optional, but may well happen to be in the correct state.
Software Engineer at Raspberry Pi Ltd. Views expressed are still personal views.
I'm not interested in doing contracts for bespoke functionality - please don't ask.

aBUGSworstnightmare
Posts: 9277
Joined: Tue Jun 30, 2015 1:35 pm

Re: Replacing SPI control signals by GPIO expander fails

Tue Nov 28, 2023 5:39 pm

6by9 wrote:
Tue Nov 28, 2023 4:27 pm
Initial guess would be timing in setting PCA9685 outputs.

Do note that you should be able to use PCA9685 directly as either PWM or GPIO outputs, making "pwm-gpio" redundant in this case.

That may well be your problem - you've used

Code: Select all

                reset-gpios = <&pca 4 GPIO_ACTIVE_HIGH>;
                dc-gpios = <&pca 5 GPIO_ACTIVE_HIGH>;
to go direct to the pca, but pwm_gpio is also registered to take pca pwm outputs 2-12.
As it's a gpiod_get_optional call from panel-mipi-dbi, it's plausible that it's failed (because the GPIO is busy), and that has significant side effects within the driver. reset is also optional, but may well happen to be in the correct state.
Isuses with the timing is also my first guess. But I should end with garbage data on the screen in such case, shouldn't I? I'm running i2c_arm at 400kHz with having 'force_turbo=1' added for testing as well (as this should give me a stable clock rate on CM4/Pi4).

O.K., let me get rid of pwm-gpio.
Also need to think if it's worth the effort to further dig into this for the sake of freeing up some GPIO ...

gadgetoid
Posts: 202
Joined: Wed Mar 07, 2012 9:58 pm

Re: Replacing SPI control signals by GPIO expander fails

Thu Dec 07, 2023 1:21 pm

I'm looking at using a PCA9685 as a PWM backlight driver *and* GPIO driver for the reset on both a gt9271 touch controller and an ilitek-ili9881 display panel. Very interested to know if you got anywhere with dropping pwm-gpio, since the comment at the top of the driver source does explicitly call out the PCA9685 as a device you might want to use it with - https://github.com/raspberrypi/linux/bl ... o-pwm.c#L7
Wrangler of code @ Pimoroni
Maintainer of pinout.xyz and pico.pinout.xyz

aBUGSworstnightmare
Posts: 9277
Joined: Tue Jun 30, 2015 1:35 pm

Re: Replacing SPI control signals by GPIO expander fails

Thu Dec 07, 2023 1:33 pm

gadgetoid wrote:
Thu Dec 07, 2023 1:21 pm
I'm looking at using a PCA9685 as a PWM backlight driver *and* GPIO driver for the reset on both a gt9271 touch controller and an ilitek-ili9881 display panel. Very interested to know if you got anywhere with dropping pwm-gpio, since the comment at the top of the driver source does explicitly call out the PCA9685 as a device you might want to use it with - https://github.com/raspberrypi/linux/bl ... o-pwm.c#L7

Code: Select all

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

			pca: pca@40 {
				compatible = "nxp,pca9685-pwm";
				#pwm-cells = <2>;
				gpio-controller;
				#gpio-cells = <2>;
				reg = <0x40>;
				status = "okay";

				gpio-line-names = "PCA_PWM0",
				  "PCA_PWM1",
				  "PCA_CS0_TFT",
				  "PCA_CS1_TP",
				  "PCA_RST",
				  "PCA_DC",
				  "PCA_AUX0",
				  "PCA_AUX1",
				  "PCA_AUX2",
				  "PCA_AUX3",
				  "PCA_AUX4",
				  "PCA_BL0_EN",
				  "PCA_BL1_EN",
				  "PCA_STATE0",
				  "PCA_STATE1",
				  "PCA_STATE2";
			};
		};
	};

	fragment@51 {
		target-path = "/";
		__overlay__ {
			backlight_spi0: backlight_spi0 {
				compatible = "pwm-backlight";
				brightness-levels = <0 4095>;
				num-interpolated-steps = <4096>;
				default-brightness-level = <4096>;
				pwms = <&pca 0 5000000>;
				// enable signal controlled by PCA9586-#11
				enable-gpios = <&pca 11 0>;
				status = "okay";
			};
				
			backlight_spi1: backlight_spi1 {
				compatible = "pwm-backlight";
				brightness-levels = <0 4095>;
				num-interpolated-steps = <4096>;
				default-brightness-level = <4096>;
				pwms = <&pca 1 5000000>;
				// enable signal controlled by PCA9586-#12
				enable-gpios = <&pca 12 0>;
				status = "okay";
			};

			controls: controls@0 {
				compatible = "gpio-leds";
				status = "okay";

				aux0: aux0@1 {
					label = "aux0";
					linux,default-trigger = "none";					
					gpios = <&pca 6 0>;
				};

				aux1: aux1@1 {
					label = "aux1";
					linux,default-trigger = "none";
					gpios = <&pca 7 0>;
				};

				aux2: aux2@1 {
					label = "aux2";
					linux,default-trigger = "none";
					gpios = <&pca 8 0>;
				};

				aux3: aux3@1 {
					label = "aux3";
					linux,default-trigger = "none";
					gpios = <&pca 9 0>;
				};

				aux4: aux4@1 {
					label = "aux4";
					linux,default-trigger = "none";
					gpios = <&pca 10 0>;
				};																									
			};

			leds: leds@0 {
				compatible = "pwm-leds";
				status = "okay";

				// available PWM range for LED 0 - 255
				state0: state0@13 {
					label = "state0";
					pwms = <&pca 13 5000000>;
					pwm-names = "state0";
				};

				state1: state1@14 {
					label = "state1";
					pwms = <&pca 14 5000000>;
					pwm-names = "state1";
				};

				state2: state2@15 {
					label = "state2";
					pwms = <&pca 15 5000000>;
					pwm-names = "state2";
				};
			};
		};
	};
That will give you two PWM-backlights - with 4096 steps resolution, 3 PWM-LEDs with 256 steps resolution, 5 GPIO-LEDs (on/off or triggered/pattern whatever you will do with LEDs). I'm using them as control signals - i.e. if your panel offers inputs for changing the scan direction you can easily do that from your config.txt then..

Code: Select all

	__overrides__ {
	..
		aux1_low = <&aux1>,"default-state=off";
		aux1_high = <&aux1>,"default-state=on";
Note that there are some 'unitialized' channels - i.e. no4 --> use it as reset with a definition as below; straight forward as with any GPIO expander

Code: Select all

                reset-gpios = <&pca 4 GPIO_ACTIVE_HIGH>;
Think you should get the point from that.

6by9
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 15880
Joined: Wed Dec 04, 2013 11:27 am
Location: ZZ9 Plural Z Alpha, aka just outside Cambridge.

Re: Replacing SPI control signals by GPIO expander fails

Thu Dec 07, 2023 1:57 pm

gadgetoid wrote:
Thu Dec 07, 2023 1:21 pm
I'm looking at using a PCA9685 as a PWM backlight driver *and* GPIO driver for the reset on both a gt9271 touch controller and an ilitek-ili9881 display panel. Very interested to know if you got anywhere with dropping pwm-gpio, since the comment at the top of the driver source does explicitly call out the PCA9685 as a device you might want to use it with - https://github.com/raspberrypi/linux/bl ... o-pwm.c#L7
Note that pwm-gpio is a downstream only driver.
At the time I wrote it, I either hadn't appreciated that PCA9685 could also function as a GPIO controller, or was also looking at other devices as well which didn't include that option but pca9685 was the easiest test bed. It was long enough ago that I really can't remember which it was.
...
A search appears to say it came from viewtopic.php?p=1924153#p1924153, so it was that I just hadn't registered that pca9685a could act as a GPIO controller.
Software Engineer at Raspberry Pi Ltd. Views expressed are still personal views.
I'm not interested in doing contracts for bespoke functionality - please don't ask.

gadgetoid
Posts: 202
Joined: Wed Mar 07, 2012 9:58 pm

Re: Replacing SPI control signals by GPIO expander fails

Thu Dec 07, 2023 3:44 pm

aBUGSworstnightmare wrote:
Thu Dec 07, 2023 1:33 pm
Think you should get the point from that.
Really useful, thank you!

The following seems to do *something*, but I've got to tweak/compile a panel driver before I can see the pieces- hopefully- come together-

Code: Select all

/dts-v1/;
/plugin/;

/ {
	compatible = "brcm,bcm2835";

	fragment@0 {
		target = <&i2c0if>;
		__overlay__ {
			status = "okay";
		};
	};
		
	fragment@1 {
		target = <&i2c0mux>;
		__overlay__ {
			status = "okay";
		};
	};

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

			pca: pca@56 {
				compatible = "nxp,pca9685-pwm";
				#pwm-cells = <2>;
				gpio-controller;
				#gpio-cells = <2>;
				reg = <0x56>;
				status = "okay";

				gpio-line-names = "PCA_PWM0",
					"PCA_PWM1",
					"PCA_PWM2",
					"PCA_PWM3",
					"PCA_PWM4",
					"PCA_PWM5",
					"PCA_PWM6",
					"PCA_PWM7",
					"PCA_GPIO8_LCD_RST",
					"PCA_PWM9_LCD_BL",
					"PCA_GPIO10_TOUCH_RST",
					"PCA_PWM11",
					"PCA_PWM12",
					"PCA_PWM13",
					"PCA_PWM14",
					"PCA_PWM15";
			};
		};
	};

	fragment@3 {
		target-path = "/";
		__overlay__ {
			backlight_lcd: backlight_lcd {
				compatible = "pwm-backlight";
				brightness-levels = <0 4095>;
				num-interpolated-steps = <4096>;
				default-brightness-level = <4096>;
				pwms = <&pca 9 5000000>;
				status = "okay";
			};
		};
	};

	fragment@4 {
		target = <&i2c_csi_dsi>;
		__overlay__ {
			#address-cells = <1>;
			#size-cells = <0>;
			status = "okay";
			gt9271@5D {
				compatible = "goodix,gt9271";
				reg = <0x5D>;
                reset-gpios = <&pca 10 0>;
				pinctrl-names = "default";
				pinctrl-0 = <&pca>;
			};
		};
	};
};
The backlight works as expected, and the touch driver has at least loaded.

I expected gpioinfo to show 9 and 10 as in-use, but gpioinfo doesn't seem to identify any consumer:

Code: Select all

gpiochip5 - 16 lines:
	line   0:   "PCA_PWM0"       unused  output  active-high 
	line   1:   "PCA_PWM1"       unused  output  active-high 
	line   2:   "PCA_PWM2"       unused  output  active-high 
	line   3:   "PCA_PWM3"       unused  output  active-high 
	line   4:   "PCA_PWM4"       unused  output  active-high 
	line   5:   "PCA_PWM5"       unused  output  active-high 
	line   6:   "PCA_PWM6"       unused  output  active-high 
	line   7:   "PCA_PWM7"       unused  output  active-high 
	line   8: "PCA_GPIO8_LCD_RST" unused output active-high 
	line   9: "PCA_PWM9_LCD_BL" unused output active-high 
	line  10: "PCA_GPIO10_TOUCH_RST" unused output active-high 
	line  11:  "PCA_PWM11"       unused  output  active-high 
	line  12:  "PCA_PWM12"       unused  output  active-high 
	line  13:  "PCA_PWM13"       unused  output  active-high 
	line  14:  "PCA_PWM14"       unused  output  active-high 
	line  15:  "PCA_PWM15"       unused  output  active-high 
I tried toggling a pin with gpiod and confirmed with my scope for bonus points, so I think I'm on the right track. Thanks again!

I'm so happy to be working with DSI instead of DPI, haha.
Wrangler of code @ Pimoroni
Maintainer of pinout.xyz and pico.pinout.xyz

aBUGSworstnightmare
Posts: 9277
Joined: Tue Jun 30, 2015 1:35 pm

Re: Replacing SPI control signals by GPIO expander fails

Thu Dec 07, 2023 3:58 pm

Let me check something. But will take some time as I've not compiled a custom kernel on this OS release yet (and I'm only compiling overlays in tree because of the includes I'm typ using -> less pain in the back).

aBUGSworstnightmare
Posts: 9277
Joined: Tue Jun 30, 2015 1:35 pm

Re: Replacing SPI control signals by GPIO expander fails

Thu Dec 07, 2023 5:31 pm

This overlay

Code: Select all

// Definitions for NXP PCA9685A I2C PWM controller on I2C0 and a 
// dumb DSI display on DSI1.
// i2c-pwm-pca9685a-test-overlay.dts
/dts-v1/;
/plugin/;

#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/leds/common.h>

/{
	compatible = "brcm,bcm2711";

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

			pca: pca@40 {
				compatible = "nxp,pca9685-pwm";
				#pwm-cells = <2>;
				gpio-controller;
				#gpio-cells = <2>;
				reg = <0x40>;
				status = "okay";

				gpio-line-names = "SELLVDS",				  
				  "AUX0",
				  "AUX1",
				  "AUX2",
				  "AUX3",
				  "REG_EN0",
				  "REG_EN1",
				  "EN_PCA",
				  "RST_PCA",
				  "BL_EN0",
				  "BL_EN1",				  			  				  
				  "STATUS0",
				  "STATUS1",
				  "STATUS2",
				  "PWM_BL0",
				  "PWM_BL1";				
			};
		};
	};

	fragment@1 {
		target-path = "/";
		__overlay__ {
			leds: leds@0 {
				compatible = "pwm-leds"; 		  		  
				status = "okay";

				// available PWM range for LED 0 - 255
				status0: status0@11 {
					label = "status0";
					pwms = <&pca 11 5000000>;
					pwm-names = "status0";
				};

				status1: status1@12 {
					label = "status1";
					pwms = <&pca 12 5000000>;
					pwm-names = "status1";
				};
					
				status2: status2@13 {
					label = "status2";
					pwms = <&pca 13 5000000>;
					pwm-names = "status2";
				};
			};
			
			controls: controls@0 {
				compatible = "gpio-leds";
				status = "okay";

				sellvds: sellvds@1 {
					label = "sellvds";
					linux,default-trigger = "none";					
					gpios = <&pca 0 0>;
				};

				aux0: aux0@1 {
					label = "aux0";
					linux,default-trigger = "none";					
					gpios = <&pca 1 0>;
				};
				
				aux1: aux1@1 {
					label = "aux1";
					linux,default-trigger = "none";					
					gpios = <&pca 2 0>;
				};
				
				aux2: aux2@1 {
					label = "aux2";
					linux,default-trigger = "none";					
					gpios = <&pca 3 0>;
				};
				
				aux3: aux3@1 {
					label = "aux3";
					linux,default-trigger = "none";					
					gpios = <&pca 4 0>;
				};																				
			};			
	
			backlight_lvds: backlight_lvds {
				compatible = "pwm-backlight";
				brightness-levels = <0 4095>;
				num-interpolated-steps = <4096>;
				default-brightness-level = <4096>;
				pwms = <&pca 14 5000000>;
				// enable signal controlled by PCA9586-#9
				enable-gpios = <&pca 9 0>;
				status = "okay";
			};	
				
			backlight_dsi: backlight_dsi {
				compatible = "pwm-backlight";
				brightness-levels = <0 4095>;
				num-interpolated-steps = <4096>;
				default-brightness-level = <4096>;
				pwms = <&pca 15 5000000>;
				// enable signal controlled by PCA9586-#10
				enable-gpios = <&pca 10 0>;
				status = "okay";
			};
		};
	};

    fragment@2 {
		target = <&dsi1>;
		__overlay__{
			status = "okay";
			#address-cells = <1>;
			#size-cells = <0>;
							
			port {
				dsi_out_port:endpoint {
					remote-endpoint = <&panel_dsi_port>;
				};
			};

			panel_disp1: panel_disp1@0 {
				reg = <0>;
				compatible = "lg,ld070wx3-sl01", "panel-simple-dsi";
				backlight = <&backlight_dsi>;
				port {
					panel_dsi_port: endpoint {
						remote-endpoint = <&dsi_out_port>;
					};
				};
			};
		};
    };
	
	__overrides__ {
		addr = <&pca>,"reg:0";

		sellvds_low = <&sellvds>,"default-state=off";
		sellvds_high = <&sellvds>,"default-state=on";
		aux0_low = <&aux0>,"default-state=off";
		aux0_high = <&aux0>,"default-state=on";
		aux1_low = <&aux1>,"default-state=off";
		aux1_high = <&aux1>,"default-state=on";
		aux2_low = <&aux2>,"default-state=off";
		aux2_high = <&aux2>,"default-state=on";
		aux3_low = <&aux3>,"default-state=off";
		aux3_high = <&aux3>,"default-state=on";
	};

};
will result in -> check your overlay

Code: Select all

pi@pi55thdez:~ $ sudo i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:                         -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: UU -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --                         
pi@pi55thdez:~ $ ls /sys/bus/i2c/drivers
dummy  pca9685-pwm  stmpe-i2c
pi@pi55thdez:~ $ pinctrl
 0: ip    pu | hi // ID_SD/GPIO0 = input
 1: ip    pu | hi // ID_SC/GPIO1 = input
 2: a3    pu | hi // PIN3/GPIO2 = SDA1
 3: a3    pu | hi // PIN5/GPIO3 = SCL1
 4: no    pu | -- // PIN7/GPIO4 = none
 5: no    pu | -- // PIN29/GPIO5 = none
 6: no    pu | -- // PIN31/GPIO6 = none
 7: no    pu | -- // PIN26/GPIO7 = none
 8: no    pu | -- // PIN24/GPIO8 = none
 9: no    pd | -- // PIN21/GPIO9 = none
10: no    pd | -- // PIN19/GPIO10 = none
11: no    pd | -- // PIN23/GPIO11 = none
12: no    pd | -- // PIN32/GPIO12 = none
13: no    pd | -- // PIN33/GPIO13 = none
14: no    pd | -- // PIN8/GPIO14 = none
15: no    pd | -- // PIN10/GPIO15 = none
16: no    pd | -- // PIN36/GPIO16 = none
17: no    pd | -- // PIN11/GPIO17 = none
18: no    pd | -- // PIN12/GPIO18 = none
19: no    pd | -- // PIN35/GPIO19 = none
20: no    pd | -- // PIN38/GPIO20 = none
21: no    pd | -- // PIN40/GPIO21 = none
22: no    pd | -- // PIN15/GPIO22 = none
23: no    pd | -- // PIN16/GPIO23 = none
24: no    pd | -- // PIN18/GPIO24 = none
25: no    pd | -- // PIN22/GPIO25 = none
26: no    pd | -- // PIN37/GPIO26 = none
27: no    pd | -- // PIN13/GPIO27 = none
28: no    pd | lo // PCIE_RP1_WAKE/GPIO28 = none
29: no    pu | hi // FAN_TACH/GPIO29 = none
30: no    pu | -- // HOST_SDA/GPIO30 = none
31: no    pu | -- // HOST_SCL/GPIO31 = none
32: op dh pd | hi // ETH_RST_N/GPIO32 = output
33: no    pd | lo // GPIO33 = none
34: op dl pd | lo // CD0_IO0_MICCLK/GPIO34 = output
35: no    pd | lo // CD0_IO0_MICDAT0/GPIO35 = none
36: no    pd | lo // RP1_PCIE_CLKREQ_N/GPIO36 = none
37: no    pd | lo // GPIO37 = none
38: ip    pd | hi // CD0_SDA/GPIO38 = input
39: ip    pd | hi // CD0_SCL/GPIO39 = input
40: ip    pd | hi // CD1_SDA/GPIO40 = input
41: ip    pd | hi // CD1_SCL/GPIO41 = input
42: a2    pd | hi // USB_VBUS_EN/GPIO42 = VBUS_EN1
43: a2    pu | hi // USB_OC_N/GPIO43 = VBUS_OC1
44: op dh pd | hi // RP1_STAT_LED/GPIO44 = output
45: a0    pd | hi // FAN_PWM/GPIO45 = PWM1_CHAN3
46: op dl pd | lo // CD1_IO0_MICCLK/GPIO46 = output
47: no    pd | lo // 2712_WAKE/GPIO47 = none
48: no    pd | lo // CD1_IO1_MICDAT1/GPIO48 = none
49: op dh pd | hi // EN_MAX_USB_CUR/GPIO49 = output
50: no    pd | -- // GPIO50 = none
51: no    pd | -- // GPIO51 = none
52: no    pu | -- // GPIO52 = none
53: no    pu | hi // GPIO53 = none
100: ip    pd | lo // GPIO0 = input
101: op dh pu | hi // 2712_BOOT_CS_N/GPIO1 = output
102: a6    pn | hi // 2712_BOOT_MISO/GPIO2 = VC_SPI0_MISO
103: a5    pn | hi // 2712_BOOT_MOSI/GPIO3 = VC_SPI0_MOSI
104: a6    pn | lo // 2712_BOOT_SCLK/GPIO4 = VC_SPI0_SCLK
105: ip    pd | lo // GPIO5 = input
106: ip    pd | lo // GPIO6 = input
107: ip    pd | lo // GPIO7 = input
108: ip    pd | lo // GPIO8 = input
109: ip    pd | lo // GPIO9 = input
110: ip    pd | lo // GPIO10 = input
111: ip    pd | lo // GPIO11 = input
112: ip    pd | lo // GPIO12 = input
113: ip    pd | lo // GPIO13 = input
114: a1    pd | lo // PCIE_SDA/GPIO14 = SPI_S_MOSI_OR_BSC_S_SDA
115: a1    pd | lo // PCIE_SCL/GPIO15 = SPI_S_SCK_OR_BSC_S_SCL
116: ip    pd | lo // GPIO16 = input
117: ip    pd | lo // GPIO17 = input
118: ip    pd | lo // GPIO18 = input
119: ip    pd | lo // GPIO19 = input
120: ip    pu | hi // PWR_GPIO/GPIO20 = input
121: ip    pd | lo // 2712_G21_FS/GPIO21 = input
122: ip    pd | lo // GPIO22 = input
123: ip    pd | lo // GPIO23 = input
124: a3    pn | lo // BT_RTS/GPIO24 = UART_RTS_0
125: a4    pu | lo // BT_CTS/GPIO25 = UART_CTS_0
126: a4    pn | hi // BT_TXD/GPIO26 = UART_TXD_0
127: a4    pu | hi // BT_RXD/GPIO27 = UART_RXD_0
128: op dh pd | hi // WL_ON/GPIO28 = output
129: op dh pd | hi // BT_ON/GPIO29 = output
130: a4    pn | hi // WIFI_SDIO_CLK/GPIO30 = SD2_CLK
131: a4    pu | hi // WIFI_SDIO_CMD/GPIO31 = SD2_CMD
132: a4    pd | hi // WIFI_SDIO_D0/GPIO32 = SD2_DAT0
133: a3    pu | hi // WIFI_SDIO_D1/GPIO33 = SD2_DAT1
134: a4    pn | hi // WIFI_SDIO_D2/GPIO34 = SD2_DAT2
135: a3    pn | hi // WIFI_SDIO_D3/GPIO35 = SD2_DAT3
200: ip    pd | hi // RP1_SDA/AON_GPIO0 = input
201: ip    pd | hi // RP1_SCL/AON_GPIO1 = input
202: op dh pd | hi // RP1_RUN/AON_GPIO2 = output
203: op dh pd | hi // SD_IOVDD_SEL/AON_GPIO3 = output
204: op dh pd | hi // SD_PWR_ON/AON_GPIO4 = output
205: a6    pu | lo // SD_CDET_N/AON_GPIO5 = SD_CARD_PRES_G
206: ip    pd | hi // SD_FLG_N/AON_GPIO6 = input
207: ip    pd | lo // AON_GPIO7 = input
208: ip    pd | lo // 2712_WAKE/AON_GPIO8 = input
209: op dh pd | hi // 2712_STAT_LED/AON_GPIO9 = output
210: ip    pd | lo // AON_GPIO10 = input
211: ip    pd | lo // AON_GPIO11 = input
212: ip    pd | lo // PMIC_INT/AON_GPIO12 = input
213: a3    pu | hi // UART_TX_FS/AON_GPIO13 = VC_TXD0
214: a3    pu | hi // UART_RX_FS/AON_GPIO14 = VC_RXD0
215: ip    pd | lo // AON_GPIO15 = input
216: ip    pu | hi // AON_GPIO16 = input
232: a1    -- | hi // HDMI0_SCL/AON_SGPIO0 = HDMI_TX0_BSC_SCL
233: a1    -- | hi // HDMI0_SDA/AON_SGPIO1 = HDMI_TX0_BSC_SDA
234: a1    -- | hi // HDMI1_SCL/AON_SGPIO2 = HDMI_TX1_BSC_SCL
235: a1    -- | hi // HDMI1_SDA/AON_SGPIO3 = HDMI_TX1_BSC_SDA
236: a2    -- | hi // PMIC_SCL/AON_SGPIO4 = BSC_M2_SCL
237: a2    -- | hi // PMIC_SDA/AON_SGPIO5 = BSC_M2_SDA
pi@pi55thdez:~ $ gpioinfo
gpiochip0 - 32 lines:
	line   0:          "-"       unused   input  active-high 
	line   1: "2712_BOOT_CS_N" "spi10 CS0" output active-low [used]
	line   2: "2712_BOOT_MISO" unused input active-high 
	line   3: "2712_BOOT_MOSI" unused input active-high 
	line   4: "2712_BOOT_SCLK" unused input active-high 
	line   5:          "-"       unused   input  active-high 
	line   6:          "-"       unused   input  active-high 
	line   7:          "-"       unused   input  active-high 
	line   8:          "-"       unused   input  active-high 
	line   9:          "-"       unused   input  active-high 
	line  10:          "-"       unused   input  active-high 
	line  11:          "-"       unused   input  active-high 
	line  12:          "-"       unused   input  active-high 
	line  13:          "-"       unused   input  active-high 
	line  14:   "PCIE_SDA"       unused   input  active-high 
	line  15:   "PCIE_SCL"       unused   input  active-high 
	line  16:          "-"       unused   input  active-high 
	line  17:          "-"       unused   input  active-high 
	line  18:          "-"       unused   input  active-high 
	line  19:          "-"       unused   input  active-high 
	line  20:   "PWR_GPIO" "pwr_button"   input   active-low [used]
	line  21: "2712_G21_FS" unused input active-high 
	line  22:          "-"       unused   input  active-high 
	line  23:          "-"       unused   input  active-high 
	line  24:     "BT_RTS"       unused   input  active-high 
	line  25:     "BT_CTS"       unused   input  active-high 
	line  26:     "BT_TXD"       unused   input  active-high 
	line  27:     "BT_RXD"       unused   input  active-high 
	line  28:      "WL_ON"  "wl_on_reg"  output  active-high [used]
	line  29:      "BT_ON"   "shutdown"  output  active-high [used]
	line  30: "WIFI_SDIO_CLK" unused input active-high 
	line  31: "WIFI_SDIO_CMD" unused input active-high 
gpiochip1 - 4 lines:
	line   0: "WIFI_SDIO_D0" unused input active-high 
	line   1: "WIFI_SDIO_D1" unused input active-high 
	line   2: "WIFI_SDIO_D2" unused input active-high 
	line   3: "WIFI_SDIO_D3" unused input active-high 
gpiochip2 - 17 lines:
	line   0:    "RP1_SDA"       unused   input  active-high 
	line   1:    "RP1_SCL"       unused   input  active-high 
	line   2:    "RP1_RUN" "RP1 RUN pin" output active-high [used]
	line   3: "SD_IOVDD_SEL" "vdd-sd-io" output active-high [used]
	line   4:  "SD_PWR_ON" "sd_vcc_reg"  output  active-high [used]
	line   5:  "SD_CDET_N"       unused   input  active-high 
	line   6:   "SD_FLG_N"       unused   input  active-high 
	line   7:          "-"       unused   input  active-high 
	line   8:  "2712_WAKE"       unused   input  active-high 
	line   9: "2712_STAT_LED" "ACT" output active-low [used]
	line  10:          "-"       unused   input  active-high 
	line  11:          "-"       unused   input  active-high 
	line  12:   "PMIC_INT"       unused   input  active-high 
	line  13: "UART_TX_FS"       unused   input  active-high 
	line  14: "UART_RX_FS"       unused   input  active-high 
	line  15:          "-"       unused   input  active-high 
	line  16:          "-"       unused   input  active-high 
gpiochip3 - 6 lines:
	line   0:  "HDMI0_SCL"       unused   input  active-high 
	line   1:  "HDMI0_SDA"       unused   input  active-high 
	line   2:  "HDMI1_SCL"       unused   input  active-high 
	line   3:  "HDMI1_SDA"       unused   input  active-high 
	line   4:   "PMIC_SCL"       unused   input  active-high 
	line   5:   "PMIC_SDA"       unused   input  active-high 
gpiochip4 - 54 lines:
	line   0:      "ID_SD"       unused   input  active-high 
	line   1:      "ID_SC"       unused   input  active-high 
	line   2:       "PIN3"       unused   input  active-high 
	line   3:       "PIN5"       unused   input  active-high 
	line   4:       "PIN7"       unused   input  active-high 
	line   5:      "PIN29"       unused   input  active-high 
	line   6:      "PIN31"       unused   input  active-high 
	line   7:      "PIN26"       unused   input  active-high 
	line   8:      "PIN24"       unused   input  active-high 
	line   9:      "PIN21"       unused   input  active-high 
	line  10:      "PIN19"       unused   input  active-high 
	line  11:      "PIN23"       unused   input  active-high 
	line  12:      "PIN32"       unused   input  active-high 
	line  13:      "PIN33"       unused   input  active-high 
	line  14:       "PIN8"       unused   input  active-high 
	line  15:      "PIN10"       unused   input  active-high 
	line  16:      "PIN36"       unused   input  active-high 
	line  17:      "PIN11"       unused   input  active-high 
	line  18:      "PIN12"       unused   input  active-high 
	line  19:      "PIN35"       unused   input  active-high 
	line  20:      "PIN38"       unused   input  active-high 
	line  21:      "PIN40"       unused   input  active-high 
	line  22:      "PIN15"       unused   input  active-high 
	line  23:      "PIN16"       unused   input  active-high 
	line  24:      "PIN18"       unused   input  active-high 
	line  25:      "PIN22"       unused   input  active-high 
	line  26:      "PIN37"       unused   input  active-high 
	line  27:      "PIN13"       unused   input  active-high 
	line  28: "PCIE_RP1_WAKE" unused input active-high 
	line  29:   "FAN_TACH"       unused   input  active-high 
	line  30:   "HOST_SDA"       unused   input  active-high 
	line  31:   "HOST_SCL"       unused   input  active-high 
	line  32:  "ETH_RST_N"  "phy-reset"  output   active-low [used]
	line  33:          "-"       unused   input  active-high 
	line  34: "CD0_IO0_MICCLK" "cam0_reg" output active-high [used]
	line  35: "CD0_IO0_MICDAT0" unused input active-high 
	line  36: "RP1_PCIE_CLKREQ_N" unused input active-high 
	line  37:          "-"       unused   input  active-high 
	line  38:    "CD0_SDA"       unused   input  active-high 
	line  39:    "CD0_SCL"       unused   input  active-high 
	line  40:    "CD1_SDA"       unused   input  active-high 
	line  41:    "CD1_SCL"       unused   input  active-high 
	line  42: "USB_VBUS_EN" unused output active-high 
	line  43:   "USB_OC_N"       unused   input  active-high 
	line  44: "RP1_STAT_LED" "PWR" output active-low [used]
	line  45:    "FAN_PWM"       unused  output  active-high 
	line  46: "CD1_IO0_MICCLK" "cam1_reg" output active-high [used]
	line  47:  "2712_WAKE"       unused   input  active-high 
	line  48: "CD1_IO1_MICDAT1" unused input active-high 
	line  49: "EN_MAX_USB_CUR" unused output active-high 
	line  50:          "-"       unused   input  active-high 
	line  51:          "-"       unused   input  active-high 
	line  52:          "-"       unused   input  active-high 
	line  53:          "-"       unused   input  active-high 
gpiochip5 - 16 lines:
	line   0:    "SELLVDS"    "sellvds"  output  active-high [used]
	line   1:       "AUX0"       "aux0"  output  active-high [used]
	line   2:       "AUX1"       "aux1"  output  active-high [used]
	line   3:       "AUX2"       "aux2"  output  active-high [used]
	line   4:       "AUX3"       "aux3"  output  active-high [used]
	line   5:    "REG_EN0"       unused  output  active-high 
	line   6:    "REG_EN1"       unused  output  active-high 
	line   7:     "EN_PCA"       unused  output  active-high 
	line   8:    "RST_PCA"       unused  output  active-high 
	line   9:     "BL_EN0"     "enable"  output  active-high [used]
	line  10:     "BL_EN1"     "enable"  output  active-high [used]
	line  11:    "STATUS0"       unused  output  active-high 
	line  12:    "STATUS1"       unused  output  active-high 
	line  13:    "STATUS2"       unused  output  active-high 
	line  14:    "PWM_BL0"       unused  output  active-high 
	line  15:    "PWM_BL1"       unused  output  active-high 
pi@pi55thdez:~ $ sudo cat /sys/kernel/debug/pwm
i2c/1-0040, 17 PWM devices
 pwm-0   ((null)              ): period: 0 ns duty: 0 ns polarity: normal
 pwm-1   ((null)              ): period: 0 ns duty: 0 ns polarity: normal
 pwm-2   ((null)              ): period: 0 ns duty: 0 ns polarity: normal
 pwm-3   ((null)              ): period: 0 ns duty: 0 ns polarity: normal
 pwm-4   ((null)              ): period: 0 ns duty: 0 ns polarity: normal
 pwm-5   ((null)              ): period: 0 ns duty: 0 ns polarity: normal
 pwm-6   ((null)              ): period: 0 ns duty: 0 ns polarity: normal
 pwm-7   ((null)              ): period: 0 ns duty: 0 ns polarity: normal
 pwm-8   ((null)              ): period: 0 ns duty: 0 ns polarity: normal
 pwm-9   ((null)              ): period: 0 ns duty: 0 ns polarity: normal
 pwm-10  ((null)              ): period: 0 ns duty: 0 ns polarity: normal
 pwm-11  (status0             ): requested enabled period: 5000000 ns duty: 0 ns polarity: normal
 pwm-12  (status1             ): requested enabled period: 5000000 ns duty: 0 ns polarity: normal
 pwm-13  (status2             ): requested enabled period: 5000000 ns duty: 0 ns polarity: normal
 pwm-14  (backlight_lvds      ): requested enabled period: 5000000 ns duty: 5000000 ns polarity: normal
 pwm-15  (backlight_dsi       ): requested enabled period: 5000000 ns duty: 5000000 ns polarity: normal
 pwm-16  ((null)              ): period: 0 ns duty: 0 ns polarity: normal

platform/1f0009c000.pwm, 4 PWM devices
 pwm-0   ((null)              ): period: 0 ns duty: 0 ns polarity: normal
 pwm-1   ((null)              ): period: 0 ns duty: 0 ns polarity: normal
 pwm-2   ((null)              ): period: 0 ns duty: 0 ns polarity: normal
 pwm-3   (cooling_fan         ): requested period: 41566 ns duty: 0 ns polarity: inverse

platform/107d517a80.pwm, 2 PWM devices
 pwm-0   ((null)              ): period: 0 ns duty: 0 ns polarity: normal
 pwm-1   ((null)              ): period: 0 ns duty: 0 ns polarity: normal
I have no panel connected atm, but as DSI got started, all GPIO show expected result I would say that's working.

gadgetoid
Posts: 202
Joined: Wed Mar 07, 2012 9:58 pm

Re: Replacing SPI control signals by GPIO expander fails

Fri Dec 08, 2023 9:03 am

Interesting, in your setup the PWM and enable pins are not marked as "used" in the gpioinfo output either. I'll chalk this up as expected and hope nobody tries to wiggle those pins. Going to try bringing up the panel driver today- it's already been bodged to work on a Pi 4 so aside from me being ridiculously rusty (and never very good in the first place) at this stuff, it should be plain sailing.

Thanks again. I'll chuck up a new thread if I run into anything interesting, since I've already misappropriated this one enough.
Wrangler of code @ Pimoroni
Maintainer of pinout.xyz and pico.pinout.xyz

aBUGSworstnightmare
Posts: 9277
Joined: Tue Jun 30, 2015 1:35 pm

Re: Replacing SPI control signals by GPIO expander fails

Fri Dec 08, 2023 9:43 am

gadgetoid wrote:
Fri Dec 08, 2023 9:03 am
Interesting, in your setup the PWM and enable pins are not marked as "used" in the gpioinfo output either. I'll chalk this up as expected and hope nobody tries to wiggle those pins. Going to try bringing up the panel driver today- it's already been bodged to work on a Pi 4 so aside from me being ridiculously rusty (and never very good in the first place) at this stuff, it should be plain sailing.

Thanks again. I'll chuck up a new thread if I run into anything interesting, since I've already misappropriated this one enough.
Sorry, don't get that comment!
They are sure shown as used

Code: Select all

	line   9:     "BL_EN0"     "enable"  output  active-high [used]
	line  10:     "BL_EN1"     "enable"  output  active-high [used]
The PWM will not be show used from the GPIO chip POV, you will have to check the PWM controller for that

Code: Select all

 pwm-14  (backlight_lvds      ): requested enabled period: 5000000 ns duty: 5000000 ns polarity: normal
 pwm-15  (backlight_dsi       ): requested enabled period: 5000000 ns duty: 5000000 ns polarity: normal
Vice versa the PWM controller has no idea that some channels are used as GPIO.

Return to “Device Tree”