]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
platform/x86: x86-android-tablets: Add support for getting i2c_adapter by PCI parent...
authorHans de Goede <hdegoede@redhat.com>
Mon, 4 Nov 2024 20:08:47 +0000 (21:08 +0100)
committerIlpo Järvinen <ilpo.jarvinen@linux.intel.com>
Wed, 6 Nov 2024 13:16:47 +0000 (15:16 +0200)
On the Vexia EDU ATLA 10 tablet, which ships with Android + a custom Linux
(guadalinex) using the custom Android kernel the I2C controllers are not
enumerated as ACPI devices as they typically are.

Instead they are enumerated as PCI devices which do not have ACPI firmware
nodes associated with them, so getting the i2c_adapter by the ACPI path of
its firmware node does not work.

Add support for getting the i2c_adapter by the devname() of its PCI parent
instead.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Andy Shevchenko <andy@kernel.org>
Link: https://lore.kernel.org/r/20241104200848.58693-3-hdegoede@redhat.com
Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
drivers/platform/x86/x86-android-tablets/Kconfig
drivers/platform/x86/x86-android-tablets/core.c
drivers/platform/x86/x86-android-tablets/x86-android-tablets.h

index 88d9e8f2ff24ec70cc8cc6745944331e374cbb8b..a67bddc4300757192a4d8b25430d150c0e7ea361 100644 (file)
@@ -5,7 +5,9 @@
 
 config X86_ANDROID_TABLETS
        tristate "X86 Android tablet support"
-       depends on I2C && SPI && SERIAL_DEV_BUS && ACPI && EFI && GPIOLIB && PMIC_OPREGION
+       depends on I2C && SPI && SERIAL_DEV_BUS
+       depends on GPIOLIB && PMIC_OPREGION
+       depends on ACPI && EFI && PCI
        select NEW_LEDS
        select LEDS_CLASS
        help
index 2848f651e00be2b3049730c887d605b8cd65b8d2..9551cdbac4fce5b7e81dbf092af959429ecb1722 100644 (file)
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/acpi.h>
+#include <linux/device.h>
 #include <linux/dmi.h>
 #include <linux/gpio/consumer.h>
 #include <linux/gpio/machine.h>
 #include <linux/irq.h>
 #include <linux/module.h>
+#include <linux/pci.h>
 #include <linux/platform_device.h>
 #include <linux/serdev.h>
 #include <linux/string.h>
@@ -170,6 +172,35 @@ get_i2c_adap_by_handle(const struct x86_i2c_client_info *client_info)
        return i2c_acpi_find_adapter_by_handle(handle);
 }
 
+static __init int match_parent(struct device *dev, const void *data)
+{
+       return dev->parent == data;
+}
+
+static struct i2c_adapter *
+get_i2c_adap_by_pci_parent(const struct x86_i2c_client_info *client_info)
+{
+       struct i2c_adapter *adap = NULL;
+       struct device *pdev, *adap_dev;
+
+       pdev = bus_find_device_by_name(&pci_bus_type, NULL, client_info->adapter_path);
+       if (!pdev) {
+               pr_err("Error could not find %s PCI device\n", client_info->adapter_path);
+               return NULL;
+       }
+
+       adap_dev = bus_find_device(&i2c_bus_type, NULL, pdev, match_parent);
+       if (adap_dev) {
+               adap = i2c_verify_adapter(adap_dev);
+               if (!adap)
+                       put_device(adap_dev);
+       }
+
+       put_device(pdev);
+
+       return adap;
+}
+
 static __init int x86_instantiate_i2c_client(const struct x86_dev_info *dev_info,
                                             int idx)
 {
@@ -181,7 +212,11 @@ static __init int x86_instantiate_i2c_client(const struct x86_dev_info *dev_info
        if (board_info.irq < 0)
                return board_info.irq;
 
-       adap = get_i2c_adap_by_handle(client_info);
+       if (dev_info->use_pci_devname)
+               adap = get_i2c_adap_by_pci_parent(client_info);
+       else
+               adap = get_i2c_adap_by_handle(client_info);
+
        if (!adap) {
                pr_err("error could not get %s adapter\n", client_info->adapter_path);
                return -ENODEV;
index 5517e438c7b69ae621bdc0a0ad34a66002bdbdd7..d26a4792eb0e29f95168880931949361fc78ca09 100644 (file)
@@ -91,6 +91,7 @@ struct x86_dev_info {
        int gpio_button_count;
        int (*init)(struct device *dev);
        void (*exit)(void);
+       bool use_pci_devname;
 };
 
 int x86_android_tablet_get_gpiod(const char *chip, int pin, const char *con_id,