Re: [PATCH v6 09/12] i2c: of-prober: Add regulator support

Chen-Yu Tsai
2024-09-05T15:10:48Z

On Thu, Sep 5, 2024 at 6:57 AM Doug Anderson <dianders@chromium.org> wrote:
>
> Hi,
>
> On Wed, Sep 4, 2024 at 2:01 AM Chen-Yu Tsai <wenst@chromium.org> wrote:
> >
> > This adds regulator management to the I2C OF component prober.
> > Components that the prober intends to probe likely require their
> > regulator supplies be enabled, and GPIOs be toggled to enable them or
> > bring them out of reset before they will respond to probe attempts.
> > GPIOs will be handled in the next patch.
> >
> > Without specific knowledge of each component's resource names or
> > power sequencing requirements, the prober can only enable the
> > regulator supplies all at once, and toggle the GPIOs all at once.
> > Luckily, reset pins tend to be active low, while enable pins tend to
> > be active high, so setting the raw status of all GPIO pins to high
> > should work. The wait time before and after resources are enabled
> > are collected from existing drivers and device trees.
> >
> > The prober collects resources from all possible components and enables
> > them together, instead of enabling resources and probing each component
> > one by one. The latter approach does not provide any boot time benefits
> > over simply enabling each component and letting each driver probe
> > sequentially.
> >
> > The prober will also deduplicate the resources, since on a component
> > swap out or co-layout design, the resources are always the same.
> > While duplicate regulator supplies won't cause much issue, shared
> > GPIOs don't work reliably, especially with other drivers. For the
> > same reason, the prober will release the GPIOs before the successfully
> > probed component is actually enabled.
> >
> > Signed-off-by: Chen-Yu Tsai <wenst@chromium.org>
> > ---
> > Changes since v5:
> > - Split of_regulator_bulk_get_all() return value check and explain
> > "ret == 0" case
> > - Switched to of_get_next_child_with_prefix_scoped() where applicable
> > - Used krealloc_array() instead of directly calculating size
> > - copy whole regulator array in one memcpy() call
> > - Drop "0" from struct zeroing initializer
> > - Split out regulator helper from i2c_of_probe_enable_res() to keep
> > code cleaner when combined with the next patch
> > - Added options for customizing power sequencing delay
> > - Rename i2c_of_probe_get_regulator() to i2c_of_probe_get_regulators()
> > - Add i2c_of_probe_free_regulator() helper
> >
> > Changes since v4:
> > - Split out GPIO handling to separate patch
> > - Rewrote using of_regulator_bulk_get_all()
> > - Replaced "regulators" with "regulator supplies" in debug messages
> >
> > Changes since v3:
> > - New patch
> >
> > This change is kept as a separate patch for now since the changes are
> > quite numerous.
> > ---
> > drivers/i2c/i2c-core-of-prober.c | 154 +++++++++++++++++++++++++++++--
> > include/linux/i2c.h | 10 +-
> > 2 files changed, 155 insertions(+), 9 deletions(-)
>
> I never jumped back into looking at this since you started sending new
> versions last month (sorry), but I finally did...
>
> At a high level, I have to say I'm not really a fan of the "reach into
> all of the devices, jam their regulators on, force their GPIOs high,
> and hope for the best" approach. It just feels like it's going to
> break at the first bit of slightly different hardware and cause power
> sequence violations left and right. If nothing else, regulators often
> need delays between when one regulator is enabled and the next. There
> may also be complex relationships between regulators and GPIOs, GPIOs,
> GPIOs that need to be low, or even GPIO "toggle sequences" (power on
> rail 1, wait 1 ms, assert reset, wait 10 ms, deassert reset, power on
> rail 2).
>
> IMO the only way to make this reliable is to have this stuff be much
> less automatic and much more driven by the board.
>
> I think that, in general, before the board prober checks i2c address
> then the prober should be in charge of setting up pinctrl and turning
> on regulators / GPIOs. Given that the same regulator(s) and GPIO(s)
> may be specified by different children, the prober will just have to
> pick one child to find those resources. It should have enough
> board-specific knowledge to make this choice. Then the prober should
> turn them on via a board-specific power-on sequence that's known to
> work for all the children. Then it should start probing.
>
> I think there can still be plenty of common helper functions that the
> board-specific prober can leverage, but overall I'd expect the actual
> power-on and power-off code to be board-specific.
>
> If many boards have in common that we need to turn on exactly one
> regulator + one GPIO, or just one regulator, or whatever then having a
> helper function that handles these cases is fine. ...but it should be
> one of many choices that a board proper could use and not the only
> one.

IIUC we could have the "options" data structure have much more board
specific information:

- name of node to fetch resources (regulator supplies and GPIOs) from
- names of the resources for the node given from the previous item
- delay time after each resource is toggled
- polarity in the case of GPIOs
- prober callback to do power sequencing

The "resource collection" step would use the first two items to retrieve
the regulator supplies and GPIOS instead of the bulk APIs used right now.

The power sequencing callback would use the resources combined with the
given delays to enable the supplies and toggle the GPIOs.

For now I would probably only implement a generic one regulator supply
plus one GPIO helper. That is the common case for touchscreens and
trackpads connected over a ribbon cable.

Does that sound like what you have in mind?

This next item would be a later enhancement (which isn't implemented in
this series anyway):

- optional prober callback that does actual probing

In our case it would only be used for cases where an HID-over-I2C
component shares the same address as a non-HID one, and some extra
work is needed to determine which type it is. I still need to think
about the structure of this.

Thanks
ChenYu