Making Rockchip IO domains dependency from other devices explicit

Quentin Schulz quentin.schulz at theobroma-systems.com
Tue Jun 14 05:41:06 PDT 2022


Hi all,

We have hit an issue for a product for which will send patches in the 
next few months and I'm asking for guidance on how to properly fix this 
in upstream Linux kernel (we are currently carrying a patch in our 
downstream U-Boot bootloader instead).

On some Rockchip SoCs, some SoC pins are split in what are called IO 
domains.

An IO domain is supplied power externally, by regulators from a PMIC for 
example. This external power supply is then used by the IO domain as 
"supply" for the IO pins if they are outputs.

Each IO domain can configure which voltage the IO pins will be operating 
on (1.8V or 3.0V). It is unclear if there's a voltage divider in IO 
domains for lowering from whatever the regulator is supplying to the 
supported 3.0V or 1.8V.

There already exists an IO domain driver for Rockchip SoCs[1]. This 
driver allows to explicit the relationship between the external power 
supplies and IO domains[2]. This makes sure the regulators are enabled 
by the Linux kernel so the IO domains are supplied with power.
This driver is a regulator consumer and does not offer any other 
interface for device dependency.
Currently, the IO pin 1.8/3.0V selection is made based on the voltage 
supported by the regulator attached to a specific IO domain.

And this is where the issue lies. The product has a camera sensor which 
didn't even appear on i2c until we figured out that its MCLK was 
actually oscillating between 0 and ~150mV. It appeared that after a soft 
reboot, the camera sensor would then appear on i2c. The driver of this 
camera sensor attempts an I2C transfer to check its ID, which fails the 
probe of the driver because the IO domain of the MCLK pin is not 
supplied with power yet/correctly configured (the io-domains driver 
probes after the camera driver). After configuring the IO domain 
correctly in the bootloader prior to booting the Linux kernel, the 
camera sensor is now working just fine.

In order to have my camera sensor working and not rely on what the 
bootloader set before Linux boots, I need to have the IO domain(s) 
correctly configured before the camera sensor driver probes. The issue 
is how to represent this dependency in the device tree.

It was suggested to me that we could use the power subsystem and use 
xxx-supply in DT for this, by making the io-domains driver expose a 
regulator per IO domain. This works fine if the IO pin connected to the 
device is already a power supply for that device, so we can just make 
this gpio-regulator depend on the regulator of the IO domain this IO pin 
is from. If it is not a regulator, this would mean we need to modify 
drivers to add a new power supply DT property for each driver. This can 
blow up pretty quickly and require, IMO, non-generic changes to driver 
to support SoC "quirks". Such would be the case for us, because I'd need 
to add this power supply DT property to the clock driver so that when 
the clock driver is probed, the regulators for the IO domains of the 
clocks exposed on IO pins are actually also enabled and the IO domains 
properly configured.

So I think the best way would be to have something transparent to the 
driver. Something handled on the subsystem level?

Looking a bit in the other kernel drivers to fish for inspiration and I 
stumbled upon pinctrl-sunxi driver.[3][4] This driver allows to specify 
a regulator as power supply per GPIO bank and will enable/disable it if 
there's a new user/none. The user would just need to add 
pinctrl-0/pinctrl-names to the device tree node of the device to both 
configure the GPIO correctly and enable the regulator for the bank this 
GPIO is attached to.

Technically, since the pinctrl subsystem has much of its behavior for 
consumers abstracted, this would make it a good fit for doing things 
transparently for drivers. The plan would be to have the IO domain 
driver expose pinctrl configuration nodes that are linked to a specific 
IO domain which would enable the appropriate regulator. I feel this is 
quite a reach/abuse of the pinctrl subsystem. Since the IO domain 
registers actually are configurable for 3.0V/1.8V, maybe this is 
actually "pin control" in the broad sense?

My suggestion would look like the following (based on rk3399-puma.dtsi):
'''
&io_domains {
	status = "okay";
	bt656-supply = <&vcc_1v8>;
	audio-supply = <&vcc_1v8>;
	sdmmc-supply = <&vcc_sd>;
	gpio1830-supply = <&vcc_1v8>;

	pinctrl_bt656_3v0: pinctrl-bt656-3v0 {
		pins = "bt656";
		function = "3v0";
	};

	pinctrl_bt656_1v8: pinctrl-bt656-1v8 {
		pins = "bt656";
		function = "1v8";
	};
};

&camera {
	[...]
	pinctrl-0 = <&pinctrl_bt656_3v0>;
	pinctrl-names = "default";
};
'''

We could also do checks in the driver so that the selected pinmux 
matches what the HW is capable of (e.g. if an 1.8V regulator supplies 
the IO domain and the pinctrl is requested for 3.0V it should fail). But 
that's just implementation details.

I'm looking for an upstreamable solution, would that fit the criteria?

Does anyone have something else to suggest or some feedback to give?

Feel free to correct me on my definitions or assumptions :)

I've added some contributors of this driver in Cc, I hope you don't mind.

Thanks,
Quentin

[1] 
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/soc/rockchip/io-domain.c
[2] 
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/power/rockchip-io-domain.yaml
[3] 
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/pinctrl/sunxi/pinctrl-sunxi.c
[4] 
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/pinctrl/allwinner,sun4i-a10-pinctrl.yaml



More information about the Linux-rockchip mailing list