We use some essential cookies to make our website work.

We use optional cookies, as detailed in our cookie policy, to remember your settings and understand how you use our website.

9 posts • Page 1 of 1
bart_st
Posts: 5
Joined: Fri Feb 28, 2025 10:31 am

Enforce initialization order for fragments / dummy gpio

Fri Nov 14, 2025 8:26 am

I am building a dto for a display using an Ilitek 9806e controller and a Goodix Gt911 touch controller.
These two components share a single reset line, so this reset line should only be asserted once on initialization. As the i2c address of the Goodix controller is determined during reset (depending on the state of a secondary GPIO line) I would like to use the reset code from Goodix driver and skip the reset from the Ilitek driver.

Currently, I have set the reset-gpios of the Ilitek driver to an unused GPIO line. This works and both display and touch controller are initialized correctly.

Two questions:
1) Is there a way to specify a dummy gpio for the Ilitek reset-gpios? The driver requires reset-gpios to be there, but I would prefer not to waste an actual GPIO line for this.
2) For this setup to work, the Goodix driver must be initialized before the Ilitek driver. This appears to work, but may be just dumb luck? Is there a way to enforce this initialization order?


For reference, this is my current dto:

Code: Select all

/dts-v1/;
/plugin/;
/ {
	compatible = "brcm,bcm2835";
	i2c_frag: fragment@0 {
		target = <&i2c_csi_dsi>;
		__overlay__ {
			#address-cells = <1>;
			#size-cells = <0>;
			status = "okay";
			gt911: gt911@5d {
				compatible = "goodix,gt911";
				reg = <0x5d>;
				touchscreen-x-mm = <90>;
				touchscreen-y-mm = <151>;
				reset-gpios = <&gpio 5 1>;	// 1 means GPIO_ACTIVE_LOW
				irq-gpios = <&gpio 6 0>;
				interrupt-parent = <&gpio>;
				interrupts = <6 2>;	// 2 = IRQ_TYPE_EDGE_FALLING
				touchscreen-swapped-x-y=<1>;
				touchscreen-inverted-y=<1>;
			};
		};
	};	
	
	dsi_frag: fragment@1 {
		target = <&dsi1>;
		__overlay__ {
			#address-cells = <1>;
			#size-cells = <0>;
			status = "okay";			
			port {
				dsi_out: endpoint {
					remote-endpoint = <&dsi_panel_in>;
				};
			}; 
			
			panel_disp: panel_disp@0 {
				reg = <0>;
				// Loads a modified version of the panel-ilitek-ili9806e driver
				compatible = "densitron,dmt050wvnmcmi-1a";
				
				// This is an unconnected dummy gpio, the display is reset by the touch controller init
				reset-gpios = <&gpio 8 1>;	// 1 means GPIO_ACTIVE_LOW
				
				port {
					dsi_panel_in: endpoint {
						remote-endpoint = <&dsi_out>;
					};
				};
			};
		};
	};
};
Thanks!

6by9
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 18540
Joined: Wed Dec 04, 2013 11:27 am

Re: Enforce initialization order for fragments / dummy gpio

Fri Nov 14, 2025 4:45 pm

You're actually looking to enforce the driver probe order, which is a totally different thing to the overlays that configure the devices.

As you've noted you can't share a GPIO. You can share a regulator though, and the regulator can control the GPIO.
Otherwise you really need to alter the driver so that https://github.com/raspberrypi/linux/bl ... 06e.c#L183

Code: Select all

ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
becomes

Code: Select all

ctx->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
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.

bart_st
Posts: 5
Joined: Fri Feb 28, 2025 10:31 am

Re: Enforce initialization order for fragments / dummy gpio

Fri Nov 21, 2025 10:40 am

Thank you for the explanation.

I tried to understand the mechanisms controlling probe order, but couldn't find anything that works at the device tree level.
I could modify the Ilitek driver to defer its probing, but the seems to introduce a tight coupling between it and the Goodix driver.

Edit: I have tried to create a phandle reference from the Ilitek to the Goodix driver:

Code: Select all

[...]
panel_disp: panel_disp@0 {
	// Ensure touchscreen is probed first to perform reset
	parent = < &gt911 >;
[...]
Empirically this seems to result in the correct probe order, but I don't know if this is actually a valid approach. Is the creation of the
"parent" dummy property correct?

Edit2: Nevermind, the phandle reference did nothing for the probe order in general.

PhilE
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 6888
Joined: Mon Sep 29, 2014 1:07 pm

Re: Enforce initialization order for fragments / dummy gpio

Mon Nov 24, 2025 10:01 am

Linux seems to deliberately avoid/prevent setting probe ordering, except via 2 methods:
1. Some subsystems (clocks, power, ???) have recognised provider/consumer relationships, where the kernel will not attempt to probe the consumer until the provider has probed successfully.
2. Returning -EPROBE_DEFER from the probe function will cause the probe to be retried later, by which time the missing dependency may be available.

bart_st
Posts: 5
Joined: Fri Feb 28, 2025 10:31 am

Re: Enforce initialization order for fragments / dummy gpio

Mon Nov 24, 2025 2:09 pm

I am trying to modify the Ilitek driver to defer its probing, but I can't figure out how to determine when the Goodix probe has completed.

I have tried this code:

Code: Select all

static int ili9806e_dsi_probe(struct mipi_dsi_device *dsi)
{
	struct device *dev = &dsi->dev;
	
	struct device_node * parent = of_parse_phandle(dev->of_node, "parent", 0);
	if (parent)
	{
		struct device *parent_dev;
		parent_dev = bus_find_device_by_of_node(&i2c_bus_type, parent);
but parent_dev exists, even if the Goodix probe is not yet complete. Furthermore, introducing this tight coupling to the i2c bus seems really wrong.

bart_st
Posts: 5
Joined: Fri Feb 28, 2025 10:31 am

Re: Enforce initialization order for fragments / dummy gpio

Mon Nov 24, 2025 3:10 pm

I have found an approach that actually works, but seems very ugly:

Code: Select all

static int ili9806e_dsi_probe(struct mipi_dsi_device *dsi)
{
	struct device *dev = &dsi->dev;
	
	struct device_node * parent = of_parse_phandle(dev->of_node, "parent", 0);
	if (parent)
	{
		struct i2c_client * parent_i2c = of_find_i2c_device_by_node(parent);
		if (parent_i2c)
		{
			void * data = dev_get_drvdata(&parent_i2c->dev);
			put_device(&parent_i2c->dev);
			
			if (!data)
			{
				printk(KERN_INFO "ili9806e parent i2c not ready, deferring");
				return -EPROBE_DEFER;
			}			
		}
[...]		
Is this really the correct way of deferring the probe?

PhilE
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 6888
Joined: Mon Sep 29, 2014 1:07 pm

Re: Enforce initialization order for fragments / dummy gpio

Mon Nov 24, 2025 3:12 pm

To recap, you have two devices on a single reset line. There should be only one actual reset, otherwise the device driver that probes first risks having the device state disappear under its feet. You would like to enforce probe ordering so that you can disconnect one of the reset lines and still guarantee that the devices are ready when the drivers run.

Looking back at your original post I noticed this question:
1) Is there a way to specify a dummy gpio for the Ilitek reset-gpios? The driver requires reset-gpios to be there, but I would prefer not to waste an actual GPIO line for this.
There is a very-non-upstream driver that allows you to create virtual GPIOs and link to them in Device Tree. It's the gpio-fsm driver, where "fsm" is short for Finite State Machine. This would allow you to create a dummy GPIO and save a pin.

However, you could actually use the FSM capability and create a system with two virtual GPIOs and one real GPIO, where the first user of the virtual reset becomes the owner of the real GPIO, and the other user is effectively ignored. Other than a DT fragment to declare and configure the gpio-fsm instance, all you would need is for the client drivers to return -EPROBE_DEFER if their respective reset GPIO is not available (because the gpio-fsm driver has not been probed yet).

It's almost 5 years since I wrote gpio-fsm, so it will take a little while to refamiliarise myself with the configuration mechanism, but essentially:
1. Declare any real input GPIOs read by the FSM.
2. Declare any real output GPIOs driven by the FSM.
3. Declare how many virtual/software GPIOs to create.
4. Optionally, set how long to wait at shutdown for a "shutdown state" to be reached.
5. Declare all the states in the system, one of which must be the "start state". Each state declares any GPIO states to set on entry to that state, any transitions to other states, and what would trigger those transitions.

In your case I think you need:
1. No real input GPIOs.
2. 1 real real output GPIO - the shared reset line.
3. 2 software GPIOs.
4. I don't think this is relevant - do you care about the state of the reset line as the reboot/power-off happens?
5. Your FSM would need 5 states:
  • Idle
    This is the start state, with the external reset deasserted.
  • reset_0
    Move into here from idle or unreset_0 when the software GPIO 0 reset is asserted
    On entry assert the real reset.
  • unreset_0
    Move into here from reset_0 when the software GPIO 0 reset is deasserted
    On entry deassert the real reset.
  • reset_1
    Move into here from idle or unreset_1 when the software GPIO 1 reset is asserted
    On entry assert the real reset.
  • unreset_1
    Move into here from reset_1 when the software GPIO 1 reset is deasserted
    On entry deassert the real reset.
Notice that only the actions from the first user to assert reset end up being acted on - the other user is ignored.

Let me know if this is something you want to try - I'll happily lend a hand.

You can read more about the gpio-fsm driver here:
viewtopic.php?p=1821505#p1821505
There is an example FSM (available as "dtoverlay=fsm-demo") declared here: https://github.com/raspberrypi/linux/bl ... verlay.dts
And a real-world usage ("dtoverlay=ghost-amp") here: https://github.com/raspberrypi/linux/bl ... verlay.dts

PhilE
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 6888
Joined: Mon Sep 29, 2014 1:07 pm

Re: Enforce initialization order for fragments / dummy gpio

Mon Nov 24, 2025 10:48 pm

This shouldn't be far off:

Code: Select all

/dts-v1/;
/plugin/;
#include <dt-bindings/gpio/gpio-fsm.h>
#define DISP_RESET GF_SW(0)
#define TS_RESET GF_SW(1)
#define SHARED_RESET GF_OP(0) // GPIO7
/{
	compatible = "brcm,bcm2835";
	fragment@0 {
		target-path = "/";
		__overlay__ {
			disp_reset: disp-reset {
				compatible = "rpi,gpio-fsm";
				debug = <0>;
				gpio-controller;
				#gpio-cells = <2>;
				num-swgpios = <2>;
				gpio-line-names = "disp_reset", "ts_reset";
				output-gpios = <&gpio 7 1>; // SHARED_RESET
				shutdown-timeout-ms = <2000>;
				idle {
					start_state;
					set = <SHARED_RESET 0>;
					reset_0 = <DISP_RESET 1>;
					reset_1 = <TS_RESET 1>;
				};
				reset_0 {
					set = <SHARED_RESET 1>;
					unreset_0 = <DISP_RESET 0>;
				};
				unreset_0 {
					set = <SHARED_RESET 0>;
					skipreset_0a = <DISP_RESET 1>;
				};
				skipreset_0a {
					skipreset_0b = <TS_RESET 1>;
				};
				skipreset_0b {
					idle = <TS_RESET 0>;
				};
				reset_1 {
					set = <SHARED_RESET 1>;
					unreset_1 = <TS_RESET 0>;
				};
				unreset_1 {
					set = <SHARED_RESET 0>;
					skipreset_1a = <TS_RESET 1>;
				};
				skipreset_1a {
					skipreset_1b = <DISP_RESET 1>;
				};
				skipreset_1b {
					idle = <DISP_RESET 0>;
				};
			};
		};
	};
	__overrides__ {
		fsm_debug = <&disp_reset>,"debug:0";
	};
};
You can add your own fragments, using "<&disp_reset 0 0>" and "<&disp_reset 1 0>" for the resets controlled by the display driver and the touchscreen driver, respectively.

I've extended the state machine so that after both resets - one echoed to the real GPIO, one ignored - it will return to the idle state. The one scenario it won't cope with is the second reset being asserted and deasserted while the first is still being asserted. That would require more states to track.

bart_st
Posts: 5
Joined: Fri Feb 28, 2025 10:31 am

Re: Enforce initialization order for fragments / dummy gpio

Tue Nov 25, 2025 7:18 am

Wow, thank you so much for the detailed response! It's very impressive how much functionality can be packed into the dt syntax.

There is unfortunately one extra complication that I only mentioned in passing in the first post: The touchscreen controller needs a second line driven during reset to configure the i2c address, afterwards this line becomes an interrupt. I guess this could also be achieved with the fsm driver, but would make the state machine even more complicated.

The approach of introducing a link between the two drivers and adding a probe deferral in the display driver seems slightly easier and more portable.

Thank you for your help though!

9 posts • Page 1 of 1

Return to "Device Tree"

AltStyle によって変換されたページ (->オリジナル) /