1157ce8f3SChen-Yu Tsai // SPDX-License-Identifier: GPL-2.0-or-later
2157ce8f3SChen-Yu Tsai /*
3157ce8f3SChen-Yu Tsai * Linux I2C core OF component prober code
4157ce8f3SChen-Yu Tsai *
5157ce8f3SChen-Yu Tsai * Copyright (C) 2024 Google LLC
6157ce8f3SChen-Yu Tsai */
7157ce8f3SChen-Yu Tsai
8157ce8f3SChen-Yu Tsai #include <linux/cleanup.h>
989726114SChen-Yu Tsai #include <linux/delay.h>
10157ce8f3SChen-Yu Tsai #include <linux/device.h>
11157ce8f3SChen-Yu Tsai #include <linux/dev_printk.h>
12157ce8f3SChen-Yu Tsai #include <linux/err.h>
1339b415f8SChen-Yu Tsai #include <linux/gpio/consumer.h>
14157ce8f3SChen-Yu Tsai #include <linux/i2c.h>
15157ce8f3SChen-Yu Tsai #include <linux/i2c-of-prober.h>
16157ce8f3SChen-Yu Tsai #include <linux/module.h>
17157ce8f3SChen-Yu Tsai #include <linux/of.h>
1889726114SChen-Yu Tsai #include <linux/regulator/consumer.h>
19157ce8f3SChen-Yu Tsai #include <linux/slab.h>
20157ce8f3SChen-Yu Tsai #include <linux/stddef.h>
21157ce8f3SChen-Yu Tsai
22157ce8f3SChen-Yu Tsai /*
23157ce8f3SChen-Yu Tsai * Some devices, such as Google Hana Chromebooks, are produced by multiple
24157ce8f3SChen-Yu Tsai * vendors each using their preferred components. Such components are all
25157ce8f3SChen-Yu Tsai * in the device tree. Instead of having all of them enabled and having each
26157ce8f3SChen-Yu Tsai * driver separately try and probe its device while fighting over shared
27157ce8f3SChen-Yu Tsai * resources, they can be marked as "fail-needs-probe" and have a prober
28157ce8f3SChen-Yu Tsai * figure out which one is actually used beforehand.
29157ce8f3SChen-Yu Tsai *
30157ce8f3SChen-Yu Tsai * This prober assumes such drop-in parts are on the same I2C bus, have
31157ce8f3SChen-Yu Tsai * non-conflicting addresses, and can be directly probed by seeing which
32157ce8f3SChen-Yu Tsai * address responds.
33157ce8f3SChen-Yu Tsai *
34157ce8f3SChen-Yu Tsai * TODO:
35157ce8f3SChen-Yu Tsai * - Support I2C muxes
36157ce8f3SChen-Yu Tsai */
37157ce8f3SChen-Yu Tsai
i2c_of_probe_get_i2c_node(struct device * dev,const char * type)38157ce8f3SChen-Yu Tsai static struct device_node *i2c_of_probe_get_i2c_node(struct device *dev, const char *type)
39157ce8f3SChen-Yu Tsai {
40157ce8f3SChen-Yu Tsai struct device_node *node __free(device_node) = of_find_node_by_name(NULL, type);
41157ce8f3SChen-Yu Tsai if (!node) {
42157ce8f3SChen-Yu Tsai dev_err(dev, "Could not find %s device node\n", type);
43157ce8f3SChen-Yu Tsai return NULL;
44157ce8f3SChen-Yu Tsai }
45157ce8f3SChen-Yu Tsai
46157ce8f3SChen-Yu Tsai struct device_node *i2c_node __free(device_node) = of_get_parent(node);
47157ce8f3SChen-Yu Tsai if (!of_node_name_eq(i2c_node, "i2c")) {
48157ce8f3SChen-Yu Tsai dev_err(dev, "%s device isn't on I2C bus\n", type);
49157ce8f3SChen-Yu Tsai return NULL;
50157ce8f3SChen-Yu Tsai }
51157ce8f3SChen-Yu Tsai
52157ce8f3SChen-Yu Tsai if (!of_device_is_available(i2c_node)) {
53157ce8f3SChen-Yu Tsai dev_err(dev, "I2C controller not available\n");
54157ce8f3SChen-Yu Tsai return NULL;
55157ce8f3SChen-Yu Tsai }
56157ce8f3SChen-Yu Tsai
57157ce8f3SChen-Yu Tsai return no_free_ptr(i2c_node);
58157ce8f3SChen-Yu Tsai }
59157ce8f3SChen-Yu Tsai
i2c_of_probe_enable_node(struct device * dev,struct device_node * node)60157ce8f3SChen-Yu Tsai static int i2c_of_probe_enable_node(struct device *dev, struct device_node *node)
61157ce8f3SChen-Yu Tsai {
62157ce8f3SChen-Yu Tsai int ret;
63157ce8f3SChen-Yu Tsai
64157ce8f3SChen-Yu Tsai dev_dbg(dev, "Enabling %pOF\n", node);
65157ce8f3SChen-Yu Tsai
66157ce8f3SChen-Yu Tsai struct of_changeset *ocs __free(kfree) = kzalloc(sizeof(*ocs), GFP_KERNEL);
67157ce8f3SChen-Yu Tsai if (!ocs)
68157ce8f3SChen-Yu Tsai return -ENOMEM;
69157ce8f3SChen-Yu Tsai
70157ce8f3SChen-Yu Tsai of_changeset_init(ocs);
71157ce8f3SChen-Yu Tsai ret = of_changeset_update_prop_string(ocs, node, "status", "okay");
72157ce8f3SChen-Yu Tsai if (ret)
73157ce8f3SChen-Yu Tsai return ret;
74157ce8f3SChen-Yu Tsai
75157ce8f3SChen-Yu Tsai ret = of_changeset_apply(ocs);
76157ce8f3SChen-Yu Tsai if (ret) {
77157ce8f3SChen-Yu Tsai /* ocs needs to be explicitly cleaned up before being freed. */
78157ce8f3SChen-Yu Tsai of_changeset_destroy(ocs);
79157ce8f3SChen-Yu Tsai } else {
80157ce8f3SChen-Yu Tsai /*
81157ce8f3SChen-Yu Tsai * ocs is intentionally kept around as it needs to
82157ce8f3SChen-Yu Tsai * exist as long as the change is applied.
83157ce8f3SChen-Yu Tsai */
84157ce8f3SChen-Yu Tsai void *ptr __always_unused = no_free_ptr(ocs);
85157ce8f3SChen-Yu Tsai }
86157ce8f3SChen-Yu Tsai
87157ce8f3SChen-Yu Tsai return ret;
88157ce8f3SChen-Yu Tsai }
89157ce8f3SChen-Yu Tsai
90157ce8f3SChen-Yu Tsai static const struct i2c_of_probe_ops i2c_of_probe_dummy_ops;
91157ce8f3SChen-Yu Tsai
92157ce8f3SChen-Yu Tsai /**
93157ce8f3SChen-Yu Tsai * i2c_of_probe_component() - probe for devices of "type" on the same i2c bus
94157ce8f3SChen-Yu Tsai * @dev: Pointer to the &struct device of the caller, only used for dev_printk() messages.
95157ce8f3SChen-Yu Tsai * @cfg: Pointer to the &struct i2c_of_probe_cfg containing callbacks and other options
96157ce8f3SChen-Yu Tsai * for the prober.
97157ce8f3SChen-Yu Tsai * @ctx: Context data for callbacks.
98157ce8f3SChen-Yu Tsai *
99157ce8f3SChen-Yu Tsai * Probe for possible I2C components of the same "type" (&i2c_of_probe_cfg->type)
100157ce8f3SChen-Yu Tsai * on the same I2C bus that have their status marked as "fail-needs-probe".
101157ce8f3SChen-Yu Tsai *
102157ce8f3SChen-Yu Tsai * Assumes that across the entire device tree the only instances of nodes
103157ce8f3SChen-Yu Tsai * with "type" prefixed node names (not including the address portion) are
104157ce8f3SChen-Yu Tsai * the ones that need handling for second source components. In other words,
105157ce8f3SChen-Yu Tsai * if "type" is "touchscreen", then all device nodes named "touchscreen*"
106157ce8f3SChen-Yu Tsai * are the ones that need probing. There cannot be another "touchscreen*"
107157ce8f3SChen-Yu Tsai * node that is already enabled.
108157ce8f3SChen-Yu Tsai *
109157ce8f3SChen-Yu Tsai * Assumes that for each "type" of component, only one actually exists. In
110157ce8f3SChen-Yu Tsai * other words, only one matching and existing device will be enabled.
111157ce8f3SChen-Yu Tsai *
112157ce8f3SChen-Yu Tsai * Context: Process context only. Does non-atomic I2C transfers.
113157ce8f3SChen-Yu Tsai * Should only be used from a driver probe function, as the function
114157ce8f3SChen-Yu Tsai * can return -EPROBE_DEFER if the I2C adapter or other resources
115157ce8f3SChen-Yu Tsai * are unavailable.
116157ce8f3SChen-Yu Tsai * Return: 0 on success or no-op, error code otherwise.
117157ce8f3SChen-Yu Tsai * A no-op can happen when it seems like the device tree already
118157ce8f3SChen-Yu Tsai * has components of the type to be probed already enabled. This
119157ce8f3SChen-Yu Tsai * can happen when the device tree had not been updated to mark
120157ce8f3SChen-Yu Tsai * the status of the to-be-probed components as "fail-needs-probe".
121157ce8f3SChen-Yu Tsai * Or this function was already run with the same parameters and
122157ce8f3SChen-Yu Tsai * succeeded in enabling a component. The latter could happen if
123157ce8f3SChen-Yu Tsai * the user had multiple types of components to probe, and one of
124157ce8f3SChen-Yu Tsai * them down the list caused a deferred probe. This is expected
125157ce8f3SChen-Yu Tsai * behavior.
126157ce8f3SChen-Yu Tsai */
i2c_of_probe_component(struct device * dev,const struct i2c_of_probe_cfg * cfg,void * ctx)127157ce8f3SChen-Yu Tsai int i2c_of_probe_component(struct device *dev, const struct i2c_of_probe_cfg *cfg, void *ctx)
128157ce8f3SChen-Yu Tsai {
129157ce8f3SChen-Yu Tsai const struct i2c_of_probe_ops *ops;
130157ce8f3SChen-Yu Tsai const char *type;
131157ce8f3SChen-Yu Tsai struct i2c_adapter *i2c;
132157ce8f3SChen-Yu Tsai int ret;
133157ce8f3SChen-Yu Tsai
134157ce8f3SChen-Yu Tsai ops = cfg->ops ?: &i2c_of_probe_dummy_ops;
135157ce8f3SChen-Yu Tsai type = cfg->type;
136157ce8f3SChen-Yu Tsai
137157ce8f3SChen-Yu Tsai struct device_node *i2c_node __free(device_node) = i2c_of_probe_get_i2c_node(dev, type);
138157ce8f3SChen-Yu Tsai if (!i2c_node)
139157ce8f3SChen-Yu Tsai return -ENODEV;
140157ce8f3SChen-Yu Tsai
141157ce8f3SChen-Yu Tsai /*
142157ce8f3SChen-Yu Tsai * If any devices of the given "type" are already enabled then this function is a no-op.
143157ce8f3SChen-Yu Tsai * Either the device tree hasn't been modified to work with this probe function, or the
144157ce8f3SChen-Yu Tsai * function had already run before and enabled some component.
145157ce8f3SChen-Yu Tsai */
146157ce8f3SChen-Yu Tsai for_each_child_of_node_with_prefix(i2c_node, node, type)
147157ce8f3SChen-Yu Tsai if (of_device_is_available(node))
148157ce8f3SChen-Yu Tsai return 0;
149157ce8f3SChen-Yu Tsai
150157ce8f3SChen-Yu Tsai i2c = of_get_i2c_adapter_by_node(i2c_node);
151157ce8f3SChen-Yu Tsai if (!i2c)
152157ce8f3SChen-Yu Tsai return dev_err_probe(dev, -EPROBE_DEFER, "Couldn't get I2C adapter\n");
153157ce8f3SChen-Yu Tsai
154157ce8f3SChen-Yu Tsai /* Grab and enable resources */
155157ce8f3SChen-Yu Tsai ret = 0;
156157ce8f3SChen-Yu Tsai if (ops->enable)
157157ce8f3SChen-Yu Tsai ret = ops->enable(dev, i2c_node, ctx);
158157ce8f3SChen-Yu Tsai if (ret)
159157ce8f3SChen-Yu Tsai goto out_put_i2c_adapter;
160157ce8f3SChen-Yu Tsai
161157ce8f3SChen-Yu Tsai for_each_child_of_node_with_prefix(i2c_node, node, type) {
162157ce8f3SChen-Yu Tsai union i2c_smbus_data data;
163157ce8f3SChen-Yu Tsai u32 addr;
164157ce8f3SChen-Yu Tsai
165157ce8f3SChen-Yu Tsai if (of_property_read_u32(node, "reg", &addr))
166157ce8f3SChen-Yu Tsai continue;
167157ce8f3SChen-Yu Tsai if (i2c_smbus_xfer(i2c, addr, 0, I2C_SMBUS_READ, 0, I2C_SMBUS_BYTE, &data) < 0)
168157ce8f3SChen-Yu Tsai continue;
169157ce8f3SChen-Yu Tsai
170157ce8f3SChen-Yu Tsai /* Found a device that is responding */
171157ce8f3SChen-Yu Tsai if (ops->cleanup_early)
172157ce8f3SChen-Yu Tsai ops->cleanup_early(dev, ctx);
173157ce8f3SChen-Yu Tsai ret = i2c_of_probe_enable_node(dev, node);
174157ce8f3SChen-Yu Tsai break;
175157ce8f3SChen-Yu Tsai }
176157ce8f3SChen-Yu Tsai
177157ce8f3SChen-Yu Tsai if (ops->cleanup)
178157ce8f3SChen-Yu Tsai ops->cleanup(dev, ctx);
179157ce8f3SChen-Yu Tsai out_put_i2c_adapter:
180157ce8f3SChen-Yu Tsai i2c_put_adapter(i2c);
181157ce8f3SChen-Yu Tsai
182157ce8f3SChen-Yu Tsai return ret;
183157ce8f3SChen-Yu Tsai }
184*cdd30ebbSPeter Zijlstra EXPORT_SYMBOL_NS_GPL(i2c_of_probe_component, "I2C_OF_PROBER");
18589726114SChen-Yu Tsai
i2c_of_probe_simple_get_supply(struct device * dev,struct device_node * node,struct i2c_of_probe_simple_ctx * ctx)18689726114SChen-Yu Tsai static int i2c_of_probe_simple_get_supply(struct device *dev, struct device_node *node,
18789726114SChen-Yu Tsai struct i2c_of_probe_simple_ctx *ctx)
18889726114SChen-Yu Tsai {
18989726114SChen-Yu Tsai const char *supply_name;
19089726114SChen-Yu Tsai struct regulator *supply;
19189726114SChen-Yu Tsai
19289726114SChen-Yu Tsai /*
19389726114SChen-Yu Tsai * It's entirely possible for the component's device node to not have the
19489726114SChen-Yu Tsai * regulator supplies. While it does not make sense from a hardware perspective,
19589726114SChen-Yu Tsai * the supplies could be always on or otherwise not modeled in the device tree,
19689726114SChen-Yu Tsai * but the device would still work.
19789726114SChen-Yu Tsai */
19889726114SChen-Yu Tsai supply_name = ctx->opts->supply_name;
19989726114SChen-Yu Tsai if (!supply_name)
20089726114SChen-Yu Tsai return 0;
20189726114SChen-Yu Tsai
20289726114SChen-Yu Tsai supply = of_regulator_get_optional(dev, node, supply_name);
20389726114SChen-Yu Tsai if (IS_ERR(supply)) {
20489726114SChen-Yu Tsai return dev_err_probe(dev, PTR_ERR(supply),
20589726114SChen-Yu Tsai "Failed to get regulator supply \"%s\" from %pOF\n",
20689726114SChen-Yu Tsai supply_name, node);
20789726114SChen-Yu Tsai }
20889726114SChen-Yu Tsai
20989726114SChen-Yu Tsai ctx->supply = supply;
21089726114SChen-Yu Tsai
21189726114SChen-Yu Tsai return 0;
21289726114SChen-Yu Tsai }
21389726114SChen-Yu Tsai
i2c_of_probe_simple_put_supply(struct i2c_of_probe_simple_ctx * ctx)21489726114SChen-Yu Tsai static void i2c_of_probe_simple_put_supply(struct i2c_of_probe_simple_ctx *ctx)
21589726114SChen-Yu Tsai {
21689726114SChen-Yu Tsai regulator_put(ctx->supply);
21789726114SChen-Yu Tsai ctx->supply = NULL;
21889726114SChen-Yu Tsai }
21989726114SChen-Yu Tsai
i2c_of_probe_simple_enable_regulator(struct device * dev,struct i2c_of_probe_simple_ctx * ctx)22089726114SChen-Yu Tsai static int i2c_of_probe_simple_enable_regulator(struct device *dev, struct i2c_of_probe_simple_ctx *ctx)
22189726114SChen-Yu Tsai {
22289726114SChen-Yu Tsai int ret;
22389726114SChen-Yu Tsai
22489726114SChen-Yu Tsai if (!ctx->supply)
22589726114SChen-Yu Tsai return 0;
22689726114SChen-Yu Tsai
22789726114SChen-Yu Tsai dev_dbg(dev, "Enabling regulator supply \"%s\"\n", ctx->opts->supply_name);
22889726114SChen-Yu Tsai
22989726114SChen-Yu Tsai ret = regulator_enable(ctx->supply);
23089726114SChen-Yu Tsai if (ret)
23189726114SChen-Yu Tsai return ret;
23289726114SChen-Yu Tsai
23389726114SChen-Yu Tsai if (ctx->opts->post_power_on_delay_ms)
23489726114SChen-Yu Tsai msleep(ctx->opts->post_power_on_delay_ms);
23589726114SChen-Yu Tsai
23689726114SChen-Yu Tsai return 0;
23789726114SChen-Yu Tsai }
23889726114SChen-Yu Tsai
i2c_of_probe_simple_disable_regulator(struct device * dev,struct i2c_of_probe_simple_ctx * ctx)23989726114SChen-Yu Tsai static void i2c_of_probe_simple_disable_regulator(struct device *dev, struct i2c_of_probe_simple_ctx *ctx)
24089726114SChen-Yu Tsai {
24189726114SChen-Yu Tsai if (!ctx->supply)
24289726114SChen-Yu Tsai return;
24389726114SChen-Yu Tsai
24489726114SChen-Yu Tsai dev_dbg(dev, "Disabling regulator supply \"%s\"\n", ctx->opts->supply_name);
24589726114SChen-Yu Tsai
24689726114SChen-Yu Tsai regulator_disable(ctx->supply);
24789726114SChen-Yu Tsai }
24889726114SChen-Yu Tsai
i2c_of_probe_simple_get_gpiod(struct device * dev,struct device_node * node,struct i2c_of_probe_simple_ctx * ctx)24939b415f8SChen-Yu Tsai static int i2c_of_probe_simple_get_gpiod(struct device *dev, struct device_node *node,
25039b415f8SChen-Yu Tsai struct i2c_of_probe_simple_ctx *ctx)
25139b415f8SChen-Yu Tsai {
25239b415f8SChen-Yu Tsai struct fwnode_handle *fwnode = of_fwnode_handle(node);
25339b415f8SChen-Yu Tsai struct gpio_desc *gpiod;
25439b415f8SChen-Yu Tsai const char *con_id;
25539b415f8SChen-Yu Tsai
25639b415f8SChen-Yu Tsai /* NULL signals no GPIO needed */
25739b415f8SChen-Yu Tsai if (!ctx->opts->gpio_name)
25839b415f8SChen-Yu Tsai return 0;
25939b415f8SChen-Yu Tsai
26039b415f8SChen-Yu Tsai /* An empty string signals an unnamed GPIO */
26139b415f8SChen-Yu Tsai if (!ctx->opts->gpio_name[0])
26239b415f8SChen-Yu Tsai con_id = NULL;
26339b415f8SChen-Yu Tsai else
26439b415f8SChen-Yu Tsai con_id = ctx->opts->gpio_name;
26539b415f8SChen-Yu Tsai
26639b415f8SChen-Yu Tsai gpiod = fwnode_gpiod_get_index(fwnode, con_id, 0, GPIOD_ASIS, "i2c-of-prober");
26739b415f8SChen-Yu Tsai if (IS_ERR(gpiod))
26839b415f8SChen-Yu Tsai return PTR_ERR(gpiod);
26939b415f8SChen-Yu Tsai
27039b415f8SChen-Yu Tsai ctx->gpiod = gpiod;
27139b415f8SChen-Yu Tsai
27239b415f8SChen-Yu Tsai return 0;
27339b415f8SChen-Yu Tsai }
27439b415f8SChen-Yu Tsai
i2c_of_probe_simple_put_gpiod(struct i2c_of_probe_simple_ctx * ctx)27539b415f8SChen-Yu Tsai static void i2c_of_probe_simple_put_gpiod(struct i2c_of_probe_simple_ctx *ctx)
27639b415f8SChen-Yu Tsai {
27739b415f8SChen-Yu Tsai gpiod_put(ctx->gpiod);
27839b415f8SChen-Yu Tsai ctx->gpiod = NULL;
27939b415f8SChen-Yu Tsai }
28039b415f8SChen-Yu Tsai
i2c_of_probe_simple_set_gpio(struct device * dev,struct i2c_of_probe_simple_ctx * ctx)28139b415f8SChen-Yu Tsai static int i2c_of_probe_simple_set_gpio(struct device *dev, struct i2c_of_probe_simple_ctx *ctx)
28239b415f8SChen-Yu Tsai {
28339b415f8SChen-Yu Tsai int ret;
28439b415f8SChen-Yu Tsai
28539b415f8SChen-Yu Tsai if (!ctx->gpiod)
28639b415f8SChen-Yu Tsai return 0;
28739b415f8SChen-Yu Tsai
28839b415f8SChen-Yu Tsai dev_dbg(dev, "Configuring GPIO\n");
28939b415f8SChen-Yu Tsai
29039b415f8SChen-Yu Tsai ret = gpiod_direction_output(ctx->gpiod, ctx->opts->gpio_assert_to_enable);
29139b415f8SChen-Yu Tsai if (ret)
29239b415f8SChen-Yu Tsai return ret;
29339b415f8SChen-Yu Tsai
29439b415f8SChen-Yu Tsai if (ctx->opts->post_gpio_config_delay_ms)
29539b415f8SChen-Yu Tsai msleep(ctx->opts->post_gpio_config_delay_ms);
29639b415f8SChen-Yu Tsai
29739b415f8SChen-Yu Tsai return 0;
29839b415f8SChen-Yu Tsai }
29939b415f8SChen-Yu Tsai
i2c_of_probe_simple_disable_gpio(struct device * dev,struct i2c_of_probe_simple_ctx * ctx)30039b415f8SChen-Yu Tsai static void i2c_of_probe_simple_disable_gpio(struct device *dev, struct i2c_of_probe_simple_ctx *ctx)
30139b415f8SChen-Yu Tsai {
30239b415f8SChen-Yu Tsai gpiod_set_value(ctx->gpiod, !ctx->opts->gpio_assert_to_enable);
30339b415f8SChen-Yu Tsai }
30439b415f8SChen-Yu Tsai
30589726114SChen-Yu Tsai /**
30689726114SChen-Yu Tsai * i2c_of_probe_simple_enable - Simple helper for I2C OF prober to get and enable resources
30789726114SChen-Yu Tsai * @dev: Pointer to the &struct device of the caller, only used for dev_printk() messages
30889726114SChen-Yu Tsai * @bus_node: Pointer to the &struct device_node of the I2C adapter.
30989726114SChen-Yu Tsai * @data: Pointer to &struct i2c_of_probe_simple_ctx helper context.
31089726114SChen-Yu Tsai *
31189726114SChen-Yu Tsai * If &i2c_of_probe_simple_opts->supply_name is given, request the named regulator supply.
31239b415f8SChen-Yu Tsai * If &i2c_of_probe_simple_opts->gpio_name is given, request the named GPIO. Or if it is
31339b415f8SChen-Yu Tsai * the empty string, request the unnamed GPIO.
31489726114SChen-Yu Tsai * If a regulator supply was found, enable that regulator.
31539b415f8SChen-Yu Tsai * If a GPIO line was found, configure the GPIO line to output and set value
31639b415f8SChen-Yu Tsai * according to given options.
31789726114SChen-Yu Tsai *
31889726114SChen-Yu Tsai * Return: %0 on success or no-op, or a negative error number on failure.
31989726114SChen-Yu Tsai */
i2c_of_probe_simple_enable(struct device * dev,struct device_node * bus_node,void * data)32089726114SChen-Yu Tsai int i2c_of_probe_simple_enable(struct device *dev, struct device_node *bus_node, void *data)
32189726114SChen-Yu Tsai {
32289726114SChen-Yu Tsai struct i2c_of_probe_simple_ctx *ctx = data;
32389726114SChen-Yu Tsai struct device_node *node;
32489726114SChen-Yu Tsai const char *compat;
32589726114SChen-Yu Tsai int ret;
32689726114SChen-Yu Tsai
32789726114SChen-Yu Tsai dev_dbg(dev, "Requesting resources for components under I2C bus %pOF\n", bus_node);
32889726114SChen-Yu Tsai
32989726114SChen-Yu Tsai if (!ctx || !ctx->opts)
33089726114SChen-Yu Tsai return -EINVAL;
33189726114SChen-Yu Tsai
33289726114SChen-Yu Tsai compat = ctx->opts->res_node_compatible;
33389726114SChen-Yu Tsai if (!compat)
33489726114SChen-Yu Tsai return -EINVAL;
33589726114SChen-Yu Tsai
33689726114SChen-Yu Tsai node = of_get_compatible_child(bus_node, compat);
33789726114SChen-Yu Tsai if (!node)
33889726114SChen-Yu Tsai return dev_err_probe(dev, -ENODEV, "No device compatible with \"%s\" found\n",
33989726114SChen-Yu Tsai compat);
34089726114SChen-Yu Tsai
34189726114SChen-Yu Tsai ret = i2c_of_probe_simple_get_supply(dev, node, ctx);
34289726114SChen-Yu Tsai if (ret)
34389726114SChen-Yu Tsai goto out_put_node;
34489726114SChen-Yu Tsai
34539b415f8SChen-Yu Tsai ret = i2c_of_probe_simple_get_gpiod(dev, node, ctx);
34689726114SChen-Yu Tsai if (ret)
34789726114SChen-Yu Tsai goto out_put_supply;
34889726114SChen-Yu Tsai
34939b415f8SChen-Yu Tsai ret = i2c_of_probe_simple_enable_regulator(dev, ctx);
35039b415f8SChen-Yu Tsai if (ret)
35139b415f8SChen-Yu Tsai goto out_put_gpiod;
35239b415f8SChen-Yu Tsai
35339b415f8SChen-Yu Tsai ret = i2c_of_probe_simple_set_gpio(dev, ctx);
35439b415f8SChen-Yu Tsai if (ret)
35539b415f8SChen-Yu Tsai goto out_disable_regulator;
35639b415f8SChen-Yu Tsai
35789726114SChen-Yu Tsai return 0;
35889726114SChen-Yu Tsai
35939b415f8SChen-Yu Tsai out_disable_regulator:
36039b415f8SChen-Yu Tsai i2c_of_probe_simple_disable_regulator(dev, ctx);
36139b415f8SChen-Yu Tsai out_put_gpiod:
36239b415f8SChen-Yu Tsai i2c_of_probe_simple_put_gpiod(ctx);
36389726114SChen-Yu Tsai out_put_supply:
36489726114SChen-Yu Tsai i2c_of_probe_simple_put_supply(ctx);
36589726114SChen-Yu Tsai out_put_node:
36689726114SChen-Yu Tsai of_node_put(node);
36789726114SChen-Yu Tsai return ret;
36889726114SChen-Yu Tsai }
369*cdd30ebbSPeter Zijlstra EXPORT_SYMBOL_NS_GPL(i2c_of_probe_simple_enable, "I2C_OF_PROBER");
37089726114SChen-Yu Tsai
37189726114SChen-Yu Tsai /**
37239b415f8SChen-Yu Tsai * i2c_of_probe_simple_cleanup_early - \
37339b415f8SChen-Yu Tsai * Simple helper for I2C OF prober to release GPIOs before component is enabled
37439b415f8SChen-Yu Tsai * @dev: Pointer to the &struct device of the caller; unused.
37539b415f8SChen-Yu Tsai * @data: Pointer to &struct i2c_of_probe_simple_ctx helper context.
37639b415f8SChen-Yu Tsai *
37739b415f8SChen-Yu Tsai * GPIO descriptors are exclusive and have to be released before the
37839b415f8SChen-Yu Tsai * actual driver probes so that the latter can acquire them.
37939b415f8SChen-Yu Tsai */
i2c_of_probe_simple_cleanup_early(struct device * dev,void * data)38039b415f8SChen-Yu Tsai void i2c_of_probe_simple_cleanup_early(struct device *dev, void *data)
38139b415f8SChen-Yu Tsai {
38239b415f8SChen-Yu Tsai struct i2c_of_probe_simple_ctx *ctx = data;
38339b415f8SChen-Yu Tsai
38439b415f8SChen-Yu Tsai i2c_of_probe_simple_put_gpiod(ctx);
38539b415f8SChen-Yu Tsai }
386*cdd30ebbSPeter Zijlstra EXPORT_SYMBOL_NS_GPL(i2c_of_probe_simple_cleanup_early, "I2C_OF_PROBER");
38739b415f8SChen-Yu Tsai
38839b415f8SChen-Yu Tsai /**
38989726114SChen-Yu Tsai * i2c_of_probe_simple_cleanup - Clean up and release resources for I2C OF prober simple helpers
39089726114SChen-Yu Tsai * @dev: Pointer to the &struct device of the caller, only used for dev_printk() messages
39189726114SChen-Yu Tsai * @data: Pointer to &struct i2c_of_probe_simple_ctx helper context.
39289726114SChen-Yu Tsai *
39339b415f8SChen-Yu Tsai * * If a GPIO line was found and not yet released, set its value to the opposite of that
39439b415f8SChen-Yu Tsai * set in i2c_of_probe_simple_enable() and release it.
39589726114SChen-Yu Tsai * * If a regulator supply was found, disable that regulator and release it.
39689726114SChen-Yu Tsai */
i2c_of_probe_simple_cleanup(struct device * dev,void * data)39789726114SChen-Yu Tsai void i2c_of_probe_simple_cleanup(struct device *dev, void *data)
39889726114SChen-Yu Tsai {
39989726114SChen-Yu Tsai struct i2c_of_probe_simple_ctx *ctx = data;
40089726114SChen-Yu Tsai
40139b415f8SChen-Yu Tsai /* GPIO operations here are no-ops if i2c_of_probe_simple_cleanup_early was called. */
40239b415f8SChen-Yu Tsai i2c_of_probe_simple_disable_gpio(dev, ctx);
40339b415f8SChen-Yu Tsai i2c_of_probe_simple_put_gpiod(ctx);
40439b415f8SChen-Yu Tsai
40589726114SChen-Yu Tsai i2c_of_probe_simple_disable_regulator(dev, ctx);
40689726114SChen-Yu Tsai i2c_of_probe_simple_put_supply(ctx);
40789726114SChen-Yu Tsai }
408*cdd30ebbSPeter Zijlstra EXPORT_SYMBOL_NS_GPL(i2c_of_probe_simple_cleanup, "I2C_OF_PROBER");
40989726114SChen-Yu Tsai
41089726114SChen-Yu Tsai struct i2c_of_probe_ops i2c_of_probe_simple_ops = {
41189726114SChen-Yu Tsai .enable = i2c_of_probe_simple_enable,
41239b415f8SChen-Yu Tsai .cleanup_early = i2c_of_probe_simple_cleanup_early,
41389726114SChen-Yu Tsai .cleanup = i2c_of_probe_simple_cleanup,
41489726114SChen-Yu Tsai };
415*cdd30ebbSPeter Zijlstra EXPORT_SYMBOL_NS_GPL(i2c_of_probe_simple_ops, "I2C_OF_PROBER");
416