From: Chen-Yu Tsai <wenst@chromium.org>
To: Rob Herring <robh@kernel.org>,
Saravana Kannan <saravanak@google.com>,
Matthias Brugger <matthias.bgg@gmail.com>,
AngeloGioacchino Del Regno
<angelogioacchino.delregno@collabora.com>,
Wolfram Sang <wsa@kernel.org>, Benson Leung <bleung@chromium.org>,
Tzung-Bi Shih <tzungbi@kernel.org>,
Mark Brown <broonie@kernel.org>,
Liam Girdwood <lgirdwood@gmail.com>
Cc: Chen-Yu Tsai <wenst@chromium.org>,
chrome-platform@lists.linux.dev, devicetree@vger.kernel.org,
linux-arm-kernel@lists.infradead.org,
linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org,
Douglas Anderson <dianders@chromium.org>,
Johan Hovold <johan@kernel.org>, Jiri Kosina <jikos@kernel.org>,
Andy Shevchenko <andriy.shevchenko@linux.intel.com>,
linux-i2c@vger.kernel.org
Subject: [PATCH v5 07/10] i2c: of-prober: Add regulator support
Date: Thu, 22 Aug 2024 17:20:00 +0800 [thread overview]
Message-ID: <20240822092006.3134096-8-wenst@chromium.org> (raw)
In-Reply-To: <20240822092006.3134096-1-wenst@chromium.org>
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 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 | 114 ++++++++++++++++++++++++++++++-
1 file changed, 113 insertions(+), 1 deletion(-)
diff --git a/drivers/i2c/i2c-core-of-prober.c b/drivers/i2c/i2c-core-of-prober.c
index bb7b231201b0..32184cfd10f6 100644
--- a/drivers/i2c/i2c-core-of-prober.c
+++ b/drivers/i2c/i2c-core-of-prober.c
@@ -6,12 +6,14 @@
*/
#include <linux/cleanup.h>
+#include <linux/delay.h>
#include <linux/device.h>
#include <linux/dev_printk.h>
#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/regulator/consumer.h>
#include <linux/slab.h>
/*
@@ -27,10 +29,93 @@
* address responds.
*
* TODO:
- * - Support handling common regulators and GPIOs.
+ * - Support handling common GPIOs.
* - Support I2C muxes
*/
+struct i2c_of_probe_data {
+ struct regulator_bulk_data *regulators;
+ unsigned int regulators_num;
+};
+
+/* Returns number of regulator supplies found for node, or error. */
+static int i2c_of_probe_get_regulator(struct device *dev, struct device_node *node,
+ struct i2c_of_probe_data *data)
+{
+ struct regulator_bulk_data *tmp, *new_regulators;
+ int ret;
+
+ ret = of_regulator_bulk_get_all(dev, node, &tmp);
+ if (ret <= 0)
+ return ret;
+
+ if (!data->regulators) {
+ data->regulators = tmp;
+ data->regulators_num = ret;
+ return ret;
+ };
+
+ new_regulators = krealloc(data->regulators,
+ sizeof(*tmp) * (data->regulators_num + ret),
+ GFP_KERNEL);
+ if (!new_regulators) {
+ regulator_bulk_free(ret, tmp);
+ return -ENOMEM;
+ }
+
+ data->regulators = new_regulators;
+
+ for (unsigned int i = 0; i < ret; i++)
+ memcpy(&data->regulators[data->regulators_num++], &tmp[i], sizeof(*tmp));
+
+ return ret;
+}
+
+static void i2c_of_probe_free_res(struct i2c_of_probe_data *data)
+{
+ regulator_bulk_free(data->regulators_num, data->regulators);
+}
+
+static int i2c_of_probe_get_res(struct device *dev, struct device_node *node,
+ struct i2c_of_probe_data *data)
+{
+ struct property *prop;
+ int ret;
+
+ ret = i2c_of_probe_get_regulator(dev, node, data);
+ if (ret < 0) {
+ dev_err_probe(dev, ret, "Failed to get regulator supplies from %pOF\n", node);
+ goto err_cleanup;
+ }
+
+ return 0;
+
+err_cleanup:
+ i2c_of_probe_free_res(data);
+ return ret;
+}
+
+static int i2c_of_probe_enable_res(struct device *dev, struct i2c_of_probe_data *data)
+{
+ int ret = 0;
+
+ dev_dbg(dev, "Enabling regulator supplies\n");
+
+ ret = regulator_bulk_enable(data->regulators_num, data->regulators);
+ if (ret)
+ return ret;
+
+ /* largest post-power-on pre-reset-deassert delay seen among drivers */
+ msleep(500);
+
+ return 0;
+}
+
+static void i2c_of_probe_disable_regulators(struct i2c_of_probe_data *data)
+{
+ regulator_bulk_disable(data->regulators_num, data->regulators);
+}
+
static struct device_node *i2c_of_probe_get_i2c_node(struct device *dev, const char *type)
{
struct device_node *node __free(device_node) = of_find_node_by_name(NULL, type);
@@ -110,6 +195,7 @@ static int i2c_of_probe_enable_node(struct device *dev, struct device_node *node
int i2c_of_probe_component(struct device *dev, const char *type)
{
struct i2c_adapter *i2c;
+ struct i2c_of_probe_data probe_data = {0};
int ret;
struct device_node *i2c_node __free(device_node) = i2c_of_probe_get_i2c_node(dev, type);
@@ -133,6 +219,30 @@ int i2c_of_probe_component(struct device *dev, const char *type)
if (!i2c)
return dev_err_probe(dev, -EPROBE_DEFER, "Couldn't get I2C adapter\n");
+ /* Grab resources */
+ for_each_child_of_node_scoped(i2c_node, node) {
+ u32 addr;
+
+ if (!of_node_name_prefix(node, type))
+ continue;
+ if (of_property_read_u32(node, "reg", &addr))
+ continue;
+
+ dev_dbg(dev, "Requesting resources for %pOF\n", node);
+ ret = i2c_of_probe_get_res(dev, node, &probe_data);
+ if (ret)
+ return ret;
+ }
+
+ dev_dbg(dev, "Resources: # of regulator supplies = %d\n", probe_data.regulators_num);
+
+ /* Enable resources */
+ ret = i2c_of_probe_enable_res(dev, &probe_data);
+ if (ret) {
+ i2c_of_probe_free_res(&probe_data);
+ return dev_err_probe(dev, ret, "Failed to enable resources\n");
+ }
+
ret = 0;
for_each_child_of_node_scoped(i2c_node, node) {
union i2c_smbus_data data;
@@ -150,6 +260,8 @@ int i2c_of_probe_component(struct device *dev, const char *type)
break;
}
+ i2c_of_probe_disable_regulators(&probe_data);
+ i2c_of_probe_free_res(&probe_data);
i2c_put_adapter(i2c);
return ret;
--
2.46.0.184.g6999bdac58-goog
next prev parent reply other threads:[~2024-08-22 9:20 UTC|newest]
Thread overview: 36+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-08-22 9:19 [PATCH v5 00/10] platform/chrome: Introduce DT hardware prober Chen-Yu Tsai
2024-08-22 9:19 ` [PATCH v5 01/10] of: dynamic: Add of_changeset_update_prop_string Chen-Yu Tsai
2024-08-22 12:32 ` Rob Herring
2024-08-22 9:19 ` [PATCH v5 02/10] regulator: Move OF-specific regulator lookup code to of_regulator.c Chen-Yu Tsai
2024-08-22 13:47 ` Andy Shevchenko
2024-08-23 6:49 ` Chen-Yu Tsai
2024-08-23 13:43 ` Andy Shevchenko
2024-08-26 6:46 ` Chen-Yu Tsai
2024-08-26 12:06 ` kernel test robot
2024-08-26 12:06 ` kernel test robot
2024-08-26 13:19 ` kernel test robot
2024-08-22 9:19 ` [PATCH v5 03/10] regulator: Split up _regulator_get() Chen-Yu Tsai
2024-08-22 13:49 ` Andy Shevchenko
2024-08-23 6:54 ` Chen-Yu Tsai
2024-08-22 9:19 ` [PATCH v5 04/10] regulator: Do pure DT regulator lookup in of_regulator_bulk_get_all() Chen-Yu Tsai
2024-08-22 13:53 ` Andy Shevchenko
2024-08-23 7:05 ` Chen-Yu Tsai
2024-08-22 9:19 ` [PATCH v5 05/10] gpiolib: Add gpio_property_name_length() Chen-Yu Tsai
2024-08-22 14:36 ` Andy Shevchenko
2024-08-23 7:50 ` Chen-Yu Tsai
2024-08-23 13:46 ` Andy Shevchenko
2024-08-22 9:19 ` [PATCH v5 06/10] i2c: Introduce OF component probe function Chen-Yu Tsai
2024-08-22 14:01 ` Andy Shevchenko
2024-08-23 8:40 ` Chen-Yu Tsai
2024-08-23 13:52 ` Andy Shevchenko
2024-08-22 9:20 ` Chen-Yu Tsai [this message]
2024-08-22 14:09 ` [PATCH v5 07/10] i2c: of-prober: Add regulator support Andy Shevchenko
2024-08-23 9:35 ` Chen-Yu Tsai
2024-08-23 13:56 ` Andy Shevchenko
2024-08-22 9:20 ` [PATCH v5 08/10] i2c: of-prober: Add GPIO support Chen-Yu Tsai
2024-08-22 14:20 ` Andy Shevchenko
2024-08-23 10:32 ` Chen-Yu Tsai
2024-08-23 14:00 ` Andy Shevchenko
2024-08-26 7:21 ` Chen-Yu Tsai
2024-08-22 9:20 ` [PATCH v5 09/10] platform/chrome: Introduce device tree hardware prober Chen-Yu Tsai
2024-08-22 9:20 ` [PATCH v5 10/10] arm64: dts: mediatek: mt8173-elm-hana: Mark touchscreens and trackpads as fail Chen-Yu Tsai
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240822092006.3134096-8-wenst@chromium.org \
--to=wenst@chromium.org \
--cc=andriy.shevchenko@linux.intel.com \
--cc=angelogioacchino.delregno@collabora.com \
--cc=bleung@chromium.org \
--cc=broonie@kernel.org \
--cc=chrome-platform@lists.linux.dev \
--cc=devicetree@vger.kernel.org \
--cc=dianders@chromium.org \
--cc=jikos@kernel.org \
--cc=johan@kernel.org \
--cc=lgirdwood@gmail.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-i2c@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mediatek@lists.infradead.org \
--cc=matthias.bgg@gmail.com \
--cc=robh@kernel.org \
--cc=saravanak@google.com \
--cc=tzungbi@kernel.org \
--cc=wsa@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox