[PATCH] CHROMIUM: i2c: Add device property for probing

From: Paul Menzel
Date: Mon Dec 20 2021 - 16:07:12 EST


From: Furquan Shaikh <furquan@xxxxxxxxxx>

Dear Linux folks,


Google Chromebooks are often built with devices sourced from different
vendors. These need to be probed. To deal with this, the firmware – in
this case coreboot – tags such optional devices accordingly – I think
this is commit fbf2c79b (drivers/i2c/generic: Add config for marking
device as probed) – and Chromium OS’ Linux kernel has the patch at hand
applied to act accordingly. Right after the merge, Dmitry created a
revert, which was actively discussed for two days but wasn’t applied.
That means, millions of devices shipped with such a firmware and Linux
kernel. To support these devices with upstream Linux kernel, is there an
alternative to applying the patch to the Linux kernel, and to support
the shipped devices?


Kind regards,

Paul


[1]: https://review.coreboot.org/c/coreboot/+/16742/
[2]: https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/1104997

--------------- 8< -------------------------- >8 ---------------

Add a new device property to indicate if an I2C device should be
probed before being added. If this property is present and set
then the I2C core layer will use i2c_new_probed_device() instead
of i2c_new_device().

This can be used to provide devices in ACPI or DT that may not be
present on the board. For example, multiple trackpad vendors can
be supported on a single board with a unified firmware image this
way by having their device address be probed before being added.

This property is styled after the PCI Host Bridge probe property
(bindings/pci/host-generic-pci.txt:linuxk,pci-probe-only) and is
a linux specific directive to alter device probing.

BUG=b:110013532
TEST=tested on soraka with 4.14 kernel:
1) add "linux,probed=1" device property to the touchscreen ACPI device
on soraka and ensure that the device is probed before being added.

tested on yorp with 4.14 kernel:
1) I2C devices without the "linux,probed=1" device property are still
functional.

Original-change-Id: I9cf689f7b75ef445c1f0e9f7ec143fa695eb398e
Original-signed-off-by: Duncan Laurie <dlaurie@xxxxxxxxxxxx>
Original-reviewed-on: https://chromium-review.googlesource.com/388767
Original-reviewed-by: Benson Leung <bleung@xxxxxxxxxxxx>

Change-Id: I54015fe102f2834f6a094d9e650c166a0cc0583b
Signed-off-by: Furquan Shaikh <furquan@xxxxxxxxxx>
Reviewed-on: https://chromium-review.googlesource.com/1100544
Commit-Ready: Furquan Shaikh <furquan@xxxxxxxxxxxx>
Tested-by: Furquan Shaikh <furquan@xxxxxxxxxxxx>
Reviewed-by: Justin TerAvest <teravest@xxxxxxxxxxxx>

Conflicts:
drivers/i2c/i2c-core-of.c

[rebase419(groeck): Context conflicts]
Signed-off-by: Guenter Roeck <groeck@xxxxxxxxxxxx>
[rebase510(groeck): Context conflicts]
Signed-off-by: Guenter Roeck <groeck@xxxxxxxxxxxx>
Change-Id: Id10adae00b381e62813fd6b8ce7c6c50f140c31b
---
Documentation/devicetree/bindings/i2c/i2c.txt | 5 +++++
drivers/i2c/i2c-core-acpi.c | 12 +++++++++++-
drivers/i2c/i2c-core-of.c | 10 +++++++++-
3 files changed, 25 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/i2c/i2c.txt b/Documentation/devicetree/bindings/i2c/i2c.txt
index b864916e087f..4921ee57f4c1 100644
--- a/Documentation/devicetree/bindings/i2c/i2c.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c.txt
@@ -133,6 +133,11 @@ wants to support one of the below features, it should adapt these bindings.
- wakeup-source
device can be used as a wakeup source.

+- linux,probed
+ If this property is present, then the I2C device will be
+ probed before being added using i2c_new_scanned_device, else
+ linux will instantiate the I2C device normally.
+
Binding may contain optional "interrupts" property, describing interrupts
used by the device. I2C core will assign "irq" interrupt (or the very first
interrupt if not using interrupt names) as primary interrupt for the slave.
diff --git a/drivers/i2c/i2c-core-acpi.c b/drivers/i2c/i2c-core-acpi.c
index 92c1cc07ed46..c970d99e4438 100644
--- a/drivers/i2c/i2c-core-acpi.c
+++ b/drivers/i2c/i2c-core-acpi.c
@@ -254,10 +254,20 @@ static void i2c_acpi_register_device(struct i2c_adapter *adapter,
struct acpi_device *adev,
struct i2c_board_info *info)
{
+ struct i2c_client *client;
+
adev->power.flags.ignore_parent = true;
acpi_device_set_enumerated(adev);

- if (IS_ERR(i2c_new_client_device(adapter, info)))
+ if (!acpi_dev_get_property(adev, "linux,probed", ACPI_TYPE_ANY, NULL)) {
+ unsigned short addrs[] = { info->addr, I2C_CLIENT_END };
+
+ client = i2c_new_scanned_device(adapter, info, addrs, NULL);
+ } else {
+ client = i2c_new_client_device(adapter, info);
+ }
+
+ if (IS_ERR(client))
adev->power.flags.ignore_parent = false;
}

diff --git a/drivers/i2c/i2c-core-of.c b/drivers/i2c/i2c-core-of.c
index 3ed74aa4b44b..fd375ce38a9e 100644
--- a/drivers/i2c/i2c-core-of.c
+++ b/drivers/i2c/i2c-core-of.c
@@ -75,7 +75,15 @@ static struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap,
if (ret)
return ERR_PTR(ret);

- client = i2c_new_client_device(adap, &info);
+ /* Allow device property to enable probing before init */
+ if (of_get_property(node, "linux,probed", NULL)) {
+ unsigned short addrs[] = { info.addr, I2C_CLIENT_END };
+
+ client = i2c_new_scanned_device(adap, &info, addrs, NULL);
+ } else {
+ client = i2c_new_client_device(adap, &info);
+ }
+
if (IS_ERR(client))
dev_err(&adap->dev, "of_i2c: Failure registering %pOF\n", node);

--
2.34.1