History

Merge tag 'i2c-for-6.13-rc1-part3' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux

Pull i2c component probing support from Wolfram Sang: "Add OF component probing. Some devices are designed and manufactured with some components having multiple drop-in replacement options. These components are often connected to the mainboard via ribbon cables, having the same signals and pin assignments across all options. These may include the display panel and touchscreen on laptops and tablets, and the trackpad on laptops. Sometimes which component option is used in a particular device can be detected by some firmware provided identifier, other times that information is not available, and the kernel has to try to probe each device. Instead of a delicate dance between drivers and device tree quirks, this change introduces a simple I2C component probe function. For a given class of devices on the same I2C bus, it will go through all of them, doing a simple I2C read transfer and see which one of them responds. It will then enable the device that responds" * tag 'i2c-for-6.13-rc1-part3' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: MAINTAINERS: fix typo in I2C OF COMPONENT PROBER of: base: Document prefix argument for of_get_next_child_with_prefix() i2c: Fix whitespace style issue arm64: dts: mediatek: mt8173-elm-hana: Mark touchscreens and trackpads as fail platform/chrome: Introduce device tree hardware prober i2c: of-prober: Add GPIO support to simple helpers i2c: of-prober: Add simple helpers for regulator support i2c: Introduce OF component probe function of: base: Add for_each_child_of_node_with_prefix() of: dynamic: Add of_changeset_update_prop_string

Linus Torvalds committed 1 year ago

Commit a14bf462 parents 88862ee caf4bdb13 files · +840 −3Browse files

Unified · Split

13 files
  1. MAINTAINERS +8 −0
  2. arch/arm64/boot/dts/mediatek/mt8173-elm-hana.dtsi +14 −0
  3. arch/arm64/boot/dts/mediatek/mt8173-elm.dtsi +2 −2
  4. drivers/i2c/Makefile +1 −0
  5. drivers/i2c/i2c-core-of-prober.c +415 −0
  6. drivers/i2c/i2c-core-smbus.c +1 −1
  7. drivers/of/base.c +36 −0
  8. drivers/of/dynamic.c +44 −0
  9. drivers/platform/chrome/Kconfig +11 −0
  10. drivers/platform/chrome/Makefile +1 −0
  11. drivers/platform/chrome/chromeos_of_hw_prober.c +154 −0
  12. include/linux/i2c-of-prober.h +140 −0
  13. include/linux/of.h +13 −0
MAINTAINERS+8−0
@@ -10758,6 +10758,14 @@ S: Maintained · 10757 unmodified lines
10758F: Documentation/devicetree/bindings/i2c/marvell,mv64xxx-i2c.yaml10758F: Documentation/devicetree/bindings/i2c/marvell,mv64xxx-i2c.yaml
10759F: drivers/i2c/busses/i2c-mv64xxx.c10759F: drivers/i2c/busses/i2c-mv64xxx.c
10760 10760
10761I2C OF COMPONENT PROBER
10762M: Chen-Yu Tsai <wenst@chromium.org>
10763L: linux-i2c@vger.kernel.org
10764L: devicetree@vger.kernel.org
10765S: Maintained
10766F: drivers/i2c/i2c-core-of-prober.c
10767F: include/linux/i2c-of-prober.h
10768
10761I2C OVER PARALLEL PORT10769I2C OVER PARALLEL PORT
10762M: Jean Delvare <jdelvare@suse.com>10770M: Jean Delvare <jdelvare@suse.com>
10763L: linux-i2c@vger.kernel.org10771L: linux-i2c@vger.kernel.org
arch/arm64/boot/dts/mediatek/mt8173-elm-hana.dtsi+14−0
@@ -14,6 +14,7 @@ · 13 unmodified lines
14 compatible = "melfas,mip4_ts";14 compatible = "melfas,mip4_ts";
15 reg = <0x34>;15 reg = <0x34>;
16 interrupts-extended = <&pio 88 IRQ_TYPE_LEVEL_LOW>;16 interrupts-extended = <&pio 88 IRQ_TYPE_LEVEL_LOW>;
17 status = "fail-needs-probe";
17 };18 };
18 19
19 /*20 /*
@@ -26,6 +27,7 @@ · 6 unmodified lines
26 reg = <0x20>;27 reg = <0x20>;
27 hid-descr-addr = <0x0020>;28 hid-descr-addr = <0x0020>;
28 interrupts-extended = <&pio 88 IRQ_TYPE_LEVEL_LOW>;29 interrupts-extended = <&pio 88 IRQ_TYPE_LEVEL_LOW>;
30 status = "fail-needs-probe";
29 };31 };
30 32
31 /* Lenovo Ideapad C330 uses G2Touch touchscreen as a 2nd source touchscreen */33 /* Lenovo Ideapad C330 uses G2Touch touchscreen as a 2nd source touchscreen */
@@ -35,6 +37,7 @@ · 3 unmodified lines
35 hid-descr-addr = <0x0001>;37 hid-descr-addr = <0x0001>;
36 interrupt-parent = <&pio>;38 interrupt-parent = <&pio>;
37 interrupts = <88 IRQ_TYPE_LEVEL_LOW>;39 interrupts = <88 IRQ_TYPE_LEVEL_LOW>;
40 status = "fail-needs-probe";
38 };41 };
39};42};
40 43
@@ -47,6 +50,8 @@ · 6 unmodified lines
47 trackpad2: trackpad@2c {50 trackpad2: trackpad@2c {
48 compatible = "hid-over-i2c";51 compatible = "hid-over-i2c";
49 interrupts-extended = <&pio 117 IRQ_TYPE_LEVEL_LOW>;52 interrupts-extended = <&pio 117 IRQ_TYPE_LEVEL_LOW>;
53 pinctrl-names = "default";
54 pinctrl-0 = <&trackpad_irq>;
50 reg = <0x2c>;55 reg = <0x2c>;
51 hid-descr-addr = <0x0020>;56 hid-descr-addr = <0x0020>;
52 /*57 /*
@@ -58,6 +63,7 @@ · 5 unmodified lines
58 */63 */
59 vdd-supply = <&mt6397_vgp6_reg>;64 vdd-supply = <&mt6397_vgp6_reg>;
60 wakeup-source;65 wakeup-source;
66 status = "fail-needs-probe";
61 };67 };
62};68};
63 69
@@ -82,3 +88,11 @@ · 18 unmodified lines
82 };88 };
83 };89 };
84};90};
91
92&touchscreen {
93 status = "fail-needs-probe";
94};
95
96&trackpad {
97 status = "fail-needs-probe";
98};
arch/arm64/boot/dts/mediatek/mt8173-elm.dtsi+2−2
@@ -358,12 +358,12 @@ · 357 unmodified lines
358&i2c4 {358&i2c4 {
359 clock-frequency = <400000>;359 clock-frequency = <400000>;
360 status = "okay";360 status = "okay";
361 pinctrl-names = "default";
362 pinctrl-0 = <&trackpad_irq>;
363 361
364 trackpad: trackpad@15 {362 trackpad: trackpad@15 {
365 compatible = "elan,ekth3000";363 compatible = "elan,ekth3000";
366 interrupts-extended = <&pio 117 IRQ_TYPE_LEVEL_LOW>;364 interrupts-extended = <&pio 117 IRQ_TYPE_LEVEL_LOW>;
365 pinctrl-names = "default";
366 pinctrl-0 = <&trackpad_irq>;
367 reg = <0x15>;367 reg = <0x15>;
368 vcc-supply = <&mt6397_vgp6_reg>;368 vcc-supply = <&mt6397_vgp6_reg>;
369 wakeup-source;369 wakeup-source;
drivers/i2c/Makefile+1−0
@@ -9,6 +9,7 @@ i2c-core-y := i2c-core-base.o i2c-core-smbus.o · 8 unmodified lines
9i2c-core-$(CONFIG_ACPI) += i2c-core-acpi.o9i2c-core-$(CONFIG_ACPI) += i2c-core-acpi.o
10i2c-core-$(CONFIG_I2C_SLAVE) += i2c-core-slave.o10i2c-core-$(CONFIG_I2C_SLAVE) += i2c-core-slave.o
11i2c-core-$(CONFIG_OF) += i2c-core-of.o11i2c-core-$(CONFIG_OF) += i2c-core-of.o
12i2c-core-$(CONFIG_OF_DYNAMIC) += i2c-core-of-prober.o
12 13
13obj-$(CONFIG_I2C_SMBUS) += i2c-smbus.o14obj-$(CONFIG_I2C_SMBUS) += i2c-smbus.o
14obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o15obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o
drivers/i2c/i2c-core-of-prober.c+415−0
@@ -0,0 +1,415 @@
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Linux I2C core OF component prober code
4 *
5 * Copyright (C) 2024 Google LLC
6 */
7
8#include <linux/cleanup.h>
9#include <linux/delay.h>
10#include <linux/device.h>
11#include <linux/dev_printk.h>
12#include <linux/err.h>
13#include <linux/gpio/consumer.h>
14#include <linux/i2c.h>
15#include <linux/i2c-of-prober.h>
16#include <linux/module.h>
17#include <linux/of.h>
18#include <linux/regulator/consumer.h>
19#include <linux/slab.h>
20#include <linux/stddef.h>
21
22/*
23 * Some devices, such as Google Hana Chromebooks, are produced by multiple
24 * vendors each using their preferred components. Such components are all
25 * in the device tree. Instead of having all of them enabled and having each
26 * driver separately try and probe its device while fighting over shared
27 * resources, they can be marked as "fail-needs-probe" and have a prober
28 * figure out which one is actually used beforehand.
29 *
30 * This prober assumes such drop-in parts are on the same I2C bus, have
31 * non-conflicting addresses, and can be directly probed by seeing which
32 * address responds.
33 *
34 * TODO:
35 * - Support I2C muxes
36 */
37
38static struct device_node *i2c_of_probe_get_i2c_node(struct device *dev, const char *type)
39{
40 struct device_node *node __free(device_node) = of_find_node_by_name(NULL, type);
41 if (!node) {
42 dev_err(dev, "Could not find %s device node\n", type);
43 return NULL;
44 }
45
46 struct device_node *i2c_node __free(device_node) = of_get_parent(node);
47 if (!of_node_name_eq(i2c_node, "i2c")) {
48 dev_err(dev, "%s device isn't on I2C bus\n", type);
49 return NULL;
50 }
51
52 if (!of_device_is_available(i2c_node)) {
53 dev_err(dev, "I2C controller not available\n");
54 return NULL;
55 }
56
57 return no_free_ptr(i2c_node);
58}
59
60static int i2c_of_probe_enable_node(struct device *dev, struct device_node *node)
61{
62 int ret;
63
64 dev_dbg(dev, "Enabling %pOF\n", node);
65
66 struct of_changeset *ocs __free(kfree) = kzalloc(sizeof(*ocs), GFP_KERNEL);
67 if (!ocs)
68 return -ENOMEM;
69
70 of_changeset_init(ocs);
71 ret = of_changeset_update_prop_string(ocs, node, "status", "okay");
72 if (ret)
73 return ret;
74
75 ret = of_changeset_apply(ocs);
76 if (ret) {
77 /* ocs needs to be explicitly cleaned up before being freed. */
78 of_changeset_destroy(ocs);
79 } else {
80 /*
81 * ocs is intentionally kept around as it needs to
82 * exist as long as the change is applied.
83 */
84 void *ptr __always_unused = no_free_ptr(ocs);
85 }
86
87 return ret;
88}
89
90static const struct i2c_of_probe_ops i2c_of_probe_dummy_ops;
91
92/**
93 * i2c_of_probe_component() - probe for devices of "type" on the same i2c bus
94 * @dev: Pointer to the &struct device of the caller, only used for dev_printk() messages.
95 * @cfg: Pointer to the &struct i2c_of_probe_cfg containing callbacks and other options
96 * for the prober.
97 * @ctx: Context data for callbacks.
98 *
99 * Probe for possible I2C components of the same "type" (&i2c_of_probe_cfg->type)
100 * on the same I2C bus that have their status marked as "fail-needs-probe".
101 *
102 * Assumes that across the entire device tree the only instances of nodes
103 * with "type" prefixed node names (not including the address portion) are
104 * the ones that need handling for second source components. In other words,
105 * if "type" is "touchscreen", then all device nodes named "touchscreen*"
106 * are the ones that need probing. There cannot be another "touchscreen*"
107 * node that is already enabled.
108 *
109 * Assumes that for each "type" of component, only one actually exists. In
110 * other words, only one matching and existing device will be enabled.
111 *
112 * Context: Process context only. Does non-atomic I2C transfers.
113 * Should only be used from a driver probe function, as the function
114 * can return -EPROBE_DEFER if the I2C adapter or other resources
115 * are unavailable.
116 * Return: 0 on success or no-op, error code otherwise.
117 * A no-op can happen when it seems like the device tree already
118 * has components of the type to be probed already enabled. This
119 * can happen when the device tree had not been updated to mark
120 * the status of the to-be-probed components as "fail-needs-probe".
121 * Or this function was already run with the same parameters and
122 * succeeded in enabling a component. The latter could happen if
123 * the user had multiple types of components to probe, and one of
124 * them down the list caused a deferred probe. This is expected
125 * behavior.
126 */
127int i2c_of_probe_component(struct device *dev, const struct i2c_of_probe_cfg *cfg, void *ctx)
128{
129 const struct i2c_of_probe_ops *ops;
130 const char *type;
131 struct i2c_adapter *i2c;
132 int ret;
133
134 ops = cfg->ops ?: &i2c_of_probe_dummy_ops;
135 type = cfg->type;
136
137 struct device_node *i2c_node __free(device_node) = i2c_of_probe_get_i2c_node(dev, type);
138 if (!i2c_node)
139 return -ENODEV;
140
141 /*
142 * If any devices of the given "type" are already enabled then this function is a no-op.
143 * Either the device tree hasn't been modified to work with this probe function, or the
144 * function had already run before and enabled some component.
145 */
146 for_each_child_of_node_with_prefix(i2c_node, node, type)
147 if (of_device_is_available(node))
148 return 0;
149
150 i2c = of_get_i2c_adapter_by_node(i2c_node);
151 if (!i2c)
152 return dev_err_probe(dev, -EPROBE_DEFER, "Couldn't get I2C adapter\n");
153
154 /* Grab and enable resources */
155 ret = 0;
156 if (ops->enable)
157 ret = ops->enable(dev, i2c_node, ctx);
158 if (ret)
159 goto out_put_i2c_adapter;
160
161 for_each_child_of_node_with_prefix(i2c_node, node, type) {
162 union i2c_smbus_data data;
163 u32 addr;
164
165 if (of_property_read_u32(node, "reg", &addr))
166 continue;
167 if (i2c_smbus_xfer(i2c, addr, 0, I2C_SMBUS_READ, 0, I2C_SMBUS_BYTE, &data) < 0)
168 continue;
169
170 /* Found a device that is responding */
171 if (ops->cleanup_early)
172 ops->cleanup_early(dev, ctx);
173 ret = i2c_of_probe_enable_node(dev, node);
174 break;
175 }
176
177 if (ops->cleanup)
178 ops->cleanup(dev, ctx);
179out_put_i2c_adapter:
180 i2c_put_adapter(i2c);
181
182 return ret;
183}
184EXPORT_SYMBOL_NS_GPL(i2c_of_probe_component, I2C_OF_PROBER);
185
186static int i2c_of_probe_simple_get_supply(struct device *dev, struct device_node *node,
187 struct i2c_of_probe_simple_ctx *ctx)
188{
189 const char *supply_name;
190 struct regulator *supply;
191
192 /*
193 * It's entirely possible for the component's device node to not have the
194 * regulator supplies. While it does not make sense from a hardware perspective,
195 * the supplies could be always on or otherwise not modeled in the device tree,
196 * but the device would still work.
197 */
198 supply_name = ctx->opts->supply_name;
199 if (!supply_name)
200 return 0;
201
202 supply = of_regulator_get_optional(dev, node, supply_name);
203 if (IS_ERR(supply)) {
204 return dev_err_probe(dev, PTR_ERR(supply),
205 "Failed to get regulator supply \"%s\" from %pOF\n",
206 supply_name, node);
207 }
208
209 ctx->supply = supply;
210
211 return 0;
212}
213
214static void i2c_of_probe_simple_put_supply(struct i2c_of_probe_simple_ctx *ctx)
215{
216 regulator_put(ctx->supply);
217 ctx->supply = NULL;
218}
219
220static int i2c_of_probe_simple_enable_regulator(struct device *dev, struct i2c_of_probe_simple_ctx *ctx)
221{
222 int ret;
223
224 if (!ctx->supply)
225 return 0;
226
227 dev_dbg(dev, "Enabling regulator supply \"%s\"\n", ctx->opts->supply_name);
228
229 ret = regulator_enable(ctx->supply);
230 if (ret)
231 return ret;
232
233 if (ctx->opts->post_power_on_delay_ms)
234 msleep(ctx->opts->post_power_on_delay_ms);
235
236 return 0;
237}
238
239static void i2c_of_probe_simple_disable_regulator(struct device *dev, struct i2c_of_probe_simple_ctx *ctx)
240{
241 if (!ctx->supply)
242 return;
243
244 dev_dbg(dev, "Disabling regulator supply \"%s\"\n", ctx->opts->supply_name);
245
246 regulator_disable(ctx->supply);
247}
248
249static int i2c_of_probe_simple_get_gpiod(struct device *dev, struct device_node *node,
250 struct i2c_of_probe_simple_ctx *ctx)
251{
252 struct fwnode_handle *fwnode = of_fwnode_handle(node);
253 struct gpio_desc *gpiod;
254 const char *con_id;
255
256 /* NULL signals no GPIO needed */
257 if (!ctx->opts->gpio_name)
258 return 0;
259
260 /* An empty string signals an unnamed GPIO */
261 if (!ctx->opts->gpio_name[0])
262 con_id = NULL;
263 else
264 con_id = ctx->opts->gpio_name;
265
266 gpiod = fwnode_gpiod_get_index(fwnode, con_id, 0, GPIOD_ASIS, "i2c-of-prober");
267 if (IS_ERR(gpiod))
268 return PTR_ERR(gpiod);
269
270 ctx->gpiod = gpiod;
271
272 return 0;
273}
274
275static void i2c_of_probe_simple_put_gpiod(struct i2c_of_probe_simple_ctx *ctx)
276{
277 gpiod_put(ctx->gpiod);
278 ctx->gpiod = NULL;
279}
280
281static int i2c_of_probe_simple_set_gpio(struct device *dev, struct i2c_of_probe_simple_ctx *ctx)
282{
283 int ret;
284
285 if (!ctx->gpiod)
286 return 0;
287
288 dev_dbg(dev, "Configuring GPIO\n");
289
290 ret = gpiod_direction_output(ctx->gpiod, ctx->opts->gpio_assert_to_enable);
291 if (ret)
292 return ret;
293
294 if (ctx->opts->post_gpio_config_delay_ms)
295 msleep(ctx->opts->post_gpio_config_delay_ms);
296
297 return 0;
298}
299
300static void i2c_of_probe_simple_disable_gpio(struct device *dev, struct i2c_of_probe_simple_ctx *ctx)
301{
302 gpiod_set_value(ctx->gpiod, !ctx->opts->gpio_assert_to_enable);
303}
304
305/**
306 * i2c_of_probe_simple_enable - Simple helper for I2C OF prober to get and enable resources
307 * @dev: Pointer to the &struct device of the caller, only used for dev_printk() messages
308 * @bus_node: Pointer to the &struct device_node of the I2C adapter.
309 * @data: Pointer to &struct i2c_of_probe_simple_ctx helper context.
310 *
311 * If &i2c_of_probe_simple_opts->supply_name is given, request the named regulator supply.
312 * If &i2c_of_probe_simple_opts->gpio_name is given, request the named GPIO. Or if it is
313 * the empty string, request the unnamed GPIO.
314 * If a regulator supply was found, enable that regulator.
315 * If a GPIO line was found, configure the GPIO line to output and set value
316 * according to given options.
317 *
318 * Return: %0 on success or no-op, or a negative error number on failure.
319 */
320int i2c_of_probe_simple_enable(struct device *dev, struct device_node *bus_node, void *data)
321{
322 struct i2c_of_probe_simple_ctx *ctx = data;
323 struct device_node *node;
324 const char *compat;
325 int ret;
326
327 dev_dbg(dev, "Requesting resources for components under I2C bus %pOF\n", bus_node);
328
329 if (!ctx || !ctx->opts)
330 return -EINVAL;
331
332 compat = ctx->opts->res_node_compatible;
333 if (!compat)
334 return -EINVAL;
335
336 node = of_get_compatible_child(bus_node, compat);
337 if (!node)
338 return dev_err_probe(dev, -ENODEV, "No device compatible with \"%s\" found\n",
339 compat);
340
341 ret = i2c_of_probe_simple_get_supply(dev, node, ctx);
342 if (ret)
343 goto out_put_node;
344
345 ret = i2c_of_probe_simple_get_gpiod(dev, node, ctx);
346 if (ret)
347 goto out_put_supply;
348
349 ret = i2c_of_probe_simple_enable_regulator(dev, ctx);
350 if (ret)
351 goto out_put_gpiod;
352
353 ret = i2c_of_probe_simple_set_gpio(dev, ctx);
354 if (ret)
355 goto out_disable_regulator;
356
357 return 0;
358
359out_disable_regulator:
360 i2c_of_probe_simple_disable_regulator(dev, ctx);
361out_put_gpiod:
362 i2c_of_probe_simple_put_gpiod(ctx);
363out_put_supply:
364 i2c_of_probe_simple_put_supply(ctx);
365out_put_node:
366 of_node_put(node);
367 return ret;
368}
369EXPORT_SYMBOL_NS_GPL(i2c_of_probe_simple_enable, I2C_OF_PROBER);
370
371/**
372 * i2c_of_probe_simple_cleanup_early - \
373 * Simple helper for I2C OF prober to release GPIOs before component is enabled
374 * @dev: Pointer to the &struct device of the caller; unused.
375 * @data: Pointer to &struct i2c_of_probe_simple_ctx helper context.
376 *
377 * GPIO descriptors are exclusive and have to be released before the
378 * actual driver probes so that the latter can acquire them.
379 */
380void i2c_of_probe_simple_cleanup_early(struct device *dev, void *data)
381{
382 struct i2c_of_probe_simple_ctx *ctx = data;
383
384 i2c_of_probe_simple_put_gpiod(ctx);
385}
386EXPORT_SYMBOL_NS_GPL(i2c_of_probe_simple_cleanup_early, I2C_OF_PROBER);
387
388/**
389 * i2c_of_probe_simple_cleanup - Clean up and release resources for I2C OF prober simple helpers
390 * @dev: Pointer to the &struct device of the caller, only used for dev_printk() messages
391 * @data: Pointer to &struct i2c_of_probe_simple_ctx helper context.
392 *
393 * * If a GPIO line was found and not yet released, set its value to the opposite of that
394 * set in i2c_of_probe_simple_enable() and release it.
395 * * If a regulator supply was found, disable that regulator and release it.
396 */
397void i2c_of_probe_simple_cleanup(struct device *dev, void *data)
398{
399 struct i2c_of_probe_simple_ctx *ctx = data;
400
401 /* GPIO operations here are no-ops if i2c_of_probe_simple_cleanup_early was called. */
402 i2c_of_probe_simple_disable_gpio(dev, ctx);
403 i2c_of_probe_simple_put_gpiod(ctx);
404
405 i2c_of_probe_simple_disable_regulator(dev, ctx);
406 i2c_of_probe_simple_put_supply(ctx);
407}
408EXPORT_SYMBOL_NS_GPL(i2c_of_probe_simple_cleanup, I2C_OF_PROBER);
409
410struct i2c_of_probe_ops i2c_of_probe_simple_ops = {
411 .enable = i2c_of_probe_simple_enable,
412 .cleanup_early = i2c_of_probe_simple_cleanup_early,
413 .cleanup = i2c_of_probe_simple_cleanup,
414};
415EXPORT_SYMBOL_NS_GPL(i2c_of_probe_simple_ops, I2C_OF_PROBER);
drivers/i2c/i2c-core-smbus.c+1−1
@@ -122,7 +122,7 @@ EXPORT_SYMBOL(i2c_smbus_read_byte); · 121 unmodified lines
122s32 i2c_smbus_write_byte(const struct i2c_client *client, u8 value)122s32 i2c_smbus_write_byte(const struct i2c_client *client, u8 value)
123{123{
124 return i2c_smbus_xfer(client->adapter, client->addr, client->flags,124 return i2c_smbus_xfer(client->adapter, client->addr, client->flags,
125 I2C_SMBUS_WRITE, value, I2C_SMBUS_BYTE, NULL);125 I2C_SMBUS_WRITE, value, I2C_SMBUS_BYTE, NULL);
126}126}
127EXPORT_SYMBOL(i2c_smbus_write_byte);127EXPORT_SYMBOL(i2c_smbus_write_byte);
128 128
drivers/of/base.c+36−0
@@ -644,6 +644,42 @@ struct device_node *of_get_next_child(const struct device_node *node, · 643 unmodified lines
644}644}
645EXPORT_SYMBOL(of_get_next_child);645EXPORT_SYMBOL(of_get_next_child);
646 646
647/**
648 * of_get_next_child_with_prefix - Find the next child node with prefix
649 * @node: parent node
650 * @prev: previous child of the parent node, or NULL to get first
651 * @prefix: prefix that the node name should have
652 *
653 * This function is like of_get_next_child(), except that it automatically
654 * skips any nodes whose name doesn't have the given prefix.
655 *
656 * Return: A node pointer with refcount incremented, use
657 * of_node_put() on it when done.
658 */
659struct device_node *of_get_next_child_with_prefix(const struct device_node *node,
660 struct device_node *prev,
661 const char *prefix)
662{
663 struct device_node *next;
664 unsigned long flags;
665
666 if (!node)
667 return NULL;
668
669 raw_spin_lock_irqsave(&devtree_lock, flags);
670 next = prev ? prev->sibling : node->child;
671 for (; next; next = next->sibling) {
672 if (!of_node_name_prefix(next, prefix))
673 continue;
674 if (of_node_get(next))
675 break;
676 }
677 of_node_put(prev);
678 raw_spin_unlock_irqrestore(&devtree_lock, flags);
679 return next;
680}
681EXPORT_SYMBOL(of_get_next_child_with_prefix);
682
647static struct device_node *of_get_next_status_child(const struct device_node *node,683static struct device_node *of_get_next_status_child(const struct device_node *node,
648 struct device_node *prev,684 struct device_node *prev,
649 bool (*checker)(const struct device_node *))685 bool (*checker)(const struct device_node *))
drivers/of/dynamic.c+44−0
@@ -1072,3 +1072,47 @@ int of_changeset_add_prop_bool(struct of_changeset *ocs, struct device_node *np, · 1071 unmodified lines
1072 return of_changeset_add_prop_helper(ocs, np, &prop);1072 return of_changeset_add_prop_helper(ocs, np, &prop);
1073}1073}
1074EXPORT_SYMBOL_GPL(of_changeset_add_prop_bool);1074EXPORT_SYMBOL_GPL(of_changeset_add_prop_bool);
1075
1076static int of_changeset_update_prop_helper(struct of_changeset *ocs,
1077 struct device_node *np,
1078 const struct property *pp)
1079{
1080 struct property *new_pp;
1081 int ret;
1082
1083 new_pp = __of_prop_dup(pp, GFP_KERNEL);
1084 if (!new_pp)
1085 return -ENOMEM;
1086
1087 ret = of_changeset_update_property(ocs, np, new_pp);
1088 if (ret)
1089 __of_prop_free(new_pp);
1090
1091 return ret;
1092}
1093
1094/**
1095 * of_changeset_update_prop_string - Add a string property update to a changeset
1096 *
1097 * @ocs: changeset pointer
1098 * @np: device node pointer
1099 * @prop_name: name of the property to be updated
1100 * @str: pointer to null terminated string
1101 *
1102 * Create a string property to be updated and add it to a changeset.
1103 *
1104 * Return: 0 on success, a negative error value in case of an error.
1105 */
1106int of_changeset_update_prop_string(struct of_changeset *ocs,
1107 struct device_node *np,
1108 const char *prop_name, const char *str)
1109{
1110 struct property prop = {
1111 .name = (char *)prop_name,
1112 .length = strlen(str) + 1,
1113 .value = (void *)str,
1114 };
1115
1116 return of_changeset_update_prop_helper(ocs, np, &prop);
1117}
1118EXPORT_SYMBOL_GPL(of_changeset_update_prop_string);
drivers/platform/chrome/Kconfig+11−0
@@ -61,6 +61,17 @@ config CHROMEOS_TBMC · 60 unmodified lines
61 To compile this driver as a module, choose M here: the61 To compile this driver as a module, choose M here: the
62 module will be called chromeos_tbmc.62 module will be called chromeos_tbmc.
63 63
64config CHROMEOS_OF_HW_PROBER
65 tristate "ChromeOS Device Tree Hardware Prober"
66 depends on OF
67 depends on I2C
68 select OF_DYNAMIC
69 default OF
70 help
71 This option enables the device tree hardware prober for ChromeOS
72 devices. The driver will probe the correct component variant in
73 devices that have multiple drop-in options for one component.
74
64config CROS_EC75config CROS_EC
65 tristate "ChromeOS Embedded Controller"76 tristate "ChromeOS Embedded Controller"
66 select CROS_EC_PROTO77 select CROS_EC_PROTO
drivers/platform/chrome/Makefile+1−0
@@ -6,6 +6,7 @@ CFLAGS_cros_ec_sensorhub_ring.o:= -I$(src) · 5 unmodified lines
6 6
7obj-$(CONFIG_CHROMEOS_ACPI) += chromeos_acpi.o7obj-$(CONFIG_CHROMEOS_ACPI) += chromeos_acpi.o
8obj-$(CONFIG_CHROMEOS_LAPTOP) += chromeos_laptop.o8obj-$(CONFIG_CHROMEOS_LAPTOP) += chromeos_laptop.o
9obj-$(CONFIG_CHROMEOS_OF_HW_PROBER) += chromeos_of_hw_prober.o
9obj-$(CONFIG_CHROMEOS_PRIVACY_SCREEN) += chromeos_privacy_screen.o10obj-$(CONFIG_CHROMEOS_PRIVACY_SCREEN) += chromeos_privacy_screen.o
10obj-$(CONFIG_CHROMEOS_PSTORE) += chromeos_pstore.o11obj-$(CONFIG_CHROMEOS_PSTORE) += chromeos_pstore.o
11obj-$(CONFIG_CHROMEOS_TBMC) += chromeos_tbmc.o12obj-$(CONFIG_CHROMEOS_TBMC) += chromeos_tbmc.o
drivers/platform/chrome/chromeos_of_hw_prober.c+154−0
@@ -0,0 +1,154 @@
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * ChromeOS Device Tree Hardware Prober
4 *
5 * Copyright (c) 2024 Google LLC
6 */
7
8#include <linux/array_size.h>
9#include <linux/errno.h>
10#include <linux/i2c-of-prober.h>
11#include <linux/module.h>
12#include <linux/of.h>
13#include <linux/platform_device.h>
14#include <linux/stddef.h>
15
16#define DRV_NAME "chromeos_of_hw_prober"
17
18/**
19 * struct hw_prober_entry - Holds an entry for the hardware prober
20 *
21 * @compatible: compatible string to match against the machine
22 * @prober: prober function to call when machine matches
23 * @data: extra data for the prober function
24 */
25struct hw_prober_entry {
26 const char *compatible;
27 int (*prober)(struct device *dev, const void *data);
28 const void *data;
29};
30
31struct chromeos_i2c_probe_data {
32 const struct i2c_of_probe_cfg *cfg;
33 const struct i2c_of_probe_simple_opts *opts;
34};
35
36static int chromeos_i2c_component_prober(struct device *dev, const void *_data)
37{
38 const struct chromeos_i2c_probe_data *data = _data;
39 struct i2c_of_probe_simple_ctx ctx = {
40 .opts = data->opts,
41 };
42
43 return i2c_of_probe_component(dev, data->cfg, &ctx);
44}
45
46#define DEFINE_CHROMEOS_I2C_PROBE_CFG_SIMPLE_BY_TYPE(_type) \
47 static const struct i2c_of_probe_cfg chromeos_i2c_probe_simple_ ## _type ## _cfg = { \
48 .type = #_type, \
49 .ops = &i2c_of_probe_simple_ops, \
50 }
51
52#define DEFINE_CHROMEOS_I2C_PROBE_DATA_DUMB_BY_TYPE(_type) \
53 static const struct chromeos_i2c_probe_data chromeos_i2c_probe_dumb_ ## _type = { \
54 .cfg = &(const struct i2c_of_probe_cfg) { \
55 .type = #_type, \
56 }, \
57 }
58
59DEFINE_CHROMEOS_I2C_PROBE_DATA_DUMB_BY_TYPE(touchscreen);
60
61DEFINE_CHROMEOS_I2C_PROBE_CFG_SIMPLE_BY_TYPE(trackpad);
62
63static const struct chromeos_i2c_probe_data chromeos_i2c_probe_hana_trackpad = {
64 .cfg = &chromeos_i2c_probe_simple_trackpad_cfg,
65 .opts = &(const struct i2c_of_probe_simple_opts) {
66 .res_node_compatible = "elan,ekth3000",
67 .supply_name = "vcc",
68 /*
69 * ELAN trackpad needs 2 ms for H/W init and 100 ms for F/W init.
70 * Synaptics trackpad needs 100 ms.
71 * However, the regulator is set to "always-on", presumably to
72 * avoid this delay. The ELAN driver is also missing delays.
73 */
74 .post_power_on_delay_ms = 0,
75 },
76};
77
78static const struct hw_prober_entry hw_prober_platforms[] = {
79 {
80 .compatible = "google,hana",
81 .prober = chromeos_i2c_component_prober,
82 .data = &chromeos_i2c_probe_dumb_touchscreen,
83 }, {
84 .compatible = "google,hana",
85 .prober = chromeos_i2c_component_prober,
86 .data = &chromeos_i2c_probe_hana_trackpad,
87 },
88};
89
90static int chromeos_of_hw_prober_probe(struct platform_device *pdev)
91{
92 for (size_t i = 0; i < ARRAY_SIZE(hw_prober_platforms); i++) {
93 int ret;
94
95 if (!of_machine_is_compatible(hw_prober_platforms[i].compatible))
96 continue;
97
98 ret = hw_prober_platforms[i].prober(&pdev->dev, hw_prober_platforms[i].data);
99 /* Ignore unrecoverable errors and keep going through other probers */
100 if (ret == -EPROBE_DEFER)
101 return ret;
102 }
103
104 return 0;
105}
106
107static struct platform_driver chromeos_of_hw_prober_driver = {
108 .probe = chromeos_of_hw_prober_probe,
109 .driver = {
110 .name = DRV_NAME,
111 },
112};
113
114static struct platform_device *chromeos_of_hw_prober_pdev;
115
116static int chromeos_of_hw_prober_driver_init(void)
117{
118 size_t i;
119 int ret;
120
121 for (i = 0; i < ARRAY_SIZE(hw_prober_platforms); i++)
122 if (of_machine_is_compatible(hw_prober_platforms[i].compatible))
123 break;
124 if (i == ARRAY_SIZE(hw_prober_platforms))
125 return -ENODEV;
126
127 ret = platform_driver_register(&chromeos_of_hw_prober_driver);
128 if (ret)
129 return ret;
130
131 chromeos_of_hw_prober_pdev =
132 platform_device_register_simple(DRV_NAME, PLATFORM_DEVID_NONE, NULL, 0);
133 if (IS_ERR(chromeos_of_hw_prober_pdev))
134 goto err;
135
136 return 0;
137
138err:
139 platform_driver_unregister(&chromeos_of_hw_prober_driver);
140
141 return PTR_ERR(chromeos_of_hw_prober_pdev);
142}
143module_init(chromeos_of_hw_prober_driver_init);
144
145static void chromeos_of_hw_prober_driver_exit(void)
146{
147 platform_device_unregister(chromeos_of_hw_prober_pdev);
148 platform_driver_unregister(&chromeos_of_hw_prober_driver);
149}
150module_exit(chromeos_of_hw_prober_driver_exit);
151
152MODULE_LICENSE("GPL");
153MODULE_DESCRIPTION("ChromeOS device tree hardware prober");
154MODULE_IMPORT_NS(I2C_OF_PROBER);
include/linux/i2c-of-prober.h+140−0
@@ -0,0 +1,140 @@
1/* SPDX-License-Identifier: GPL-2.0-or-later */
2/*
3 * Definitions for the Linux I2C OF component prober
4 *
5 * Copyright (C) 2024 Google LLC
6 */
7
8#ifndef _LINUX_I2C_OF_PROBER_H
9#define _LINUX_I2C_OF_PROBER_H
10
11#include <linux/kconfig.h>
12#include <linux/types.h>
13
14struct device;
15struct device_node;
16
17/**
18 * struct i2c_of_probe_ops - I2C OF component prober callbacks
19 *
20 * A set of callbacks to be used by i2c_of_probe_component().
21 *
22 * All callbacks are optional. Callbacks are called only once per run, and are
23 * used in the order they are defined in this structure.
24 *
25 * All callbacks that have return values shall return %0 on success,
26 * or a negative error number on failure.
27 *
28 * The @dev parameter passed to the callbacks is the same as @dev passed to
29 * i2c_of_probe_component(). It should only be used for dev_printk() calls
30 * and nothing else, especially not managed device resource (devres) APIs.
31 */
32struct i2c_of_probe_ops {
33 /**
34 * @enable: Retrieve and enable resources so that the components respond to probes.
35 *
36 * It is OK for this callback to return -EPROBE_DEFER since the intended use includes
37 * retrieving resources and enables them. Resources should be reverted to their initial
38 * state and released before returning if this fails.
39 */
40 int (*enable)(struct device *dev, struct device_node *bus_node, void *data);
41
42 /**
43 * @cleanup_early: Release exclusive resources prior to calling probe() on a
44 * detected component.
45 *
46 * Only called if a matching component is actually found. If none are found,
47 * resources that would have been released in this callback should be released in
48 * @free_resourcs_late instead.
49 */
50 void (*cleanup_early)(struct device *dev, void *data);
51
52 /**
53 * @cleanup: Opposite of @enable to balance refcounts and free resources after probing.
54 *
55 * Should check if resources were already freed by @cleanup_early.
56 */
57 void (*cleanup)(struct device *dev, void *data);
58};
59
60/**
61 * struct i2c_of_probe_cfg - I2C OF component prober configuration
62 * @ops: Callbacks for the prober to use.
63 * @type: A string to match the device node name prefix to probe for.
64 */
65struct i2c_of_probe_cfg {
66 const struct i2c_of_probe_ops *ops;
67 const char *type;
68};
69
70#if IS_ENABLED(CONFIG_OF_DYNAMIC)
71
72int i2c_of_probe_component(struct device *dev, const struct i2c_of_probe_cfg *cfg, void *ctx);
73
74/**
75 * DOC: I2C OF component prober simple helpers
76 *
77 * Components such as trackpads are commonly connected to a devices baseboard
78 * with a 6-pin ribbon cable. That gives at most one voltage supply and one
79 * GPIO (commonly a "enable" or "reset" line) besides the I2C bus, interrupt
80 * pin, and common ground. Touchscreens, while integrated into the display
81 * panel's connection, typically have the same set of connections.
82 *
83 * A simple set of helpers are provided here for use with the I2C OF component
84 * prober. This implementation targets such components, allowing for at most
85 * one regulator supply.
86 *
87 * The following helpers are provided:
88 * * i2c_of_probe_simple_enable()
89 * * i2c_of_probe_simple_cleanup_early()
90 * * i2c_of_probe_simple_cleanup()
91 */
92
93/**
94 * struct i2c_of_probe_simple_opts - Options for simple I2C component prober callbacks
95 * @res_node_compatible: Compatible string of device node to retrieve resources from.
96 * @supply_name: Name of regulator supply.
97 * @gpio_name: Name of GPIO. NULL if no GPIO line is used. Empty string ("") if GPIO
98 * line is unnamed.
99 * @post_power_on_delay_ms: Delay after regulators are powered on. Passed to msleep().
100 * @post_gpio_config_delay_ms: Delay after GPIO is configured. Passed to msleep().
101 * @gpio_assert_to_enable: %true if GPIO should be asserted, i.e. set to logical high,
102 * to enable the component.
103 *
104 * This describes power sequences common for the class of components supported by the
105 * simple component prober:
106 * * @gpio_name is configured to the non-active setting according to @gpio_assert_to_enable.
107 * * @supply_name regulator supply is enabled.
108 * * Wait for @post_power_on_delay_ms to pass.
109 * * @gpio_name is configured to the active setting according to @gpio_assert_to_enable.
110 * * Wait for @post_gpio_config_delay_ms to pass.
111 */
112struct i2c_of_probe_simple_opts {
113 const char *res_node_compatible;
114 const char *supply_name;
115 const char *gpio_name;
116 unsigned int post_power_on_delay_ms;
117 unsigned int post_gpio_config_delay_ms;
118 bool gpio_assert_to_enable;
119};
120
121struct gpio_desc;
122struct regulator;
123
124struct i2c_of_probe_simple_ctx {
125 /* public: provided by user before helpers are used. */
126 const struct i2c_of_probe_simple_opts *opts;
127 /* private: internal fields for helpers. */
128 struct regulator *supply;
129 struct gpio_desc *gpiod;
130};
131
132int i2c_of_probe_simple_enable(struct device *dev, struct device_node *bus_node, void *data);
133void i2c_of_probe_simple_cleanup_early(struct device *dev, void *data);
134void i2c_of_probe_simple_cleanup(struct device *dev, void *data);
135
136extern struct i2c_of_probe_ops i2c_of_probe_simple_ops;
137
138#endif /* IS_ENABLED(CONFIG_OF_DYNAMIC) */
139
140#endif /* _LINUX_I2C_OF_PROBER_H */
include/linux/of.h+13−0
@@ -289,6 +289,9 @@ extern struct device_node *of_get_parent(const struct device_node *node); · 288 unmodified lines
289extern struct device_node *of_get_next_parent(struct device_node *node);289extern struct device_node *of_get_next_parent(struct device_node *node);
290extern struct device_node *of_get_next_child(const struct device_node *node,290extern struct device_node *of_get_next_child(const struct device_node *node,
291 struct device_node *prev);291 struct device_node *prev);
292extern struct device_node *of_get_next_child_with_prefix(const struct device_node *node,
293 struct device_node *prev,
294 const char *prefix);
292extern struct device_node *of_get_next_available_child(295extern struct device_node *of_get_next_available_child(
293 const struct device_node *node, struct device_node *prev);296 const struct device_node *node, struct device_node *prev);
294extern struct device_node *of_get_next_reserved_child(297extern struct device_node *of_get_next_reserved_child(
@@ -1468,6 +1471,12 @@ static inline int of_property_read_s32(const struct device_node *np, · 1173 unmodified lines
1468 child != NULL; \1471 child != NULL; \
1469 child = of_get_next_child(parent, child))1472 child = of_get_next_child(parent, child))
1470 1473
1474#define for_each_child_of_node_with_prefix(parent, child, prefix) \
1475 for (struct device_node *child __free(device_node) = \
1476 of_get_next_child_with_prefix(parent, NULL, prefix); \
1477 child != NULL; \
1478 child = of_get_next_child_with_prefix(parent, child, prefix))
1479
1471#define for_each_available_child_of_node(parent, child) \1480#define for_each_available_child_of_node(parent, child) \
1472 for (child = of_get_next_available_child(parent, NULL); child != NULL; \1481 for (child = of_get_next_available_child(parent, NULL); child != NULL; \
1473 child = of_get_next_available_child(parent, child))1482 child = of_get_next_available_child(parent, child))
@@ -1651,6 +1660,10 @@ static inline int of_changeset_add_prop_u32(struct of_changeset *ocs, · 177 unmodified lines
1651 return of_changeset_add_prop_u32_array(ocs, np, prop_name, &val, 1);1660 return of_changeset_add_prop_u32_array(ocs, np, prop_name, &val, 1);
1652}1661}
1653 1662
1663int of_changeset_update_prop_string(struct of_changeset *ocs,
1664 struct device_node *np,
1665 const char *prop_name, const char *str);
1666
1654int of_changeset_add_prop_bool(struct of_changeset *ocs, struct device_node *np,1667int of_changeset_add_prop_bool(struct of_changeset *ocs, struct device_node *np,
1655 const char *prop_name);1668 const char *prop_name);
1656 1669

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t