platform/x86: x86-android-tablets: Stop using gpiolib private APIs
authorHans de Goede <hdegoede@redhat.com>
Sat, 9 Sep 2023 14:18:14 +0000 (16:18 +0200)
committerHans de Goede <hdegoede@redhat.com>
Mon, 11 Sep 2023 11:28:58 +0000 (13:28 +0200)
Refactor x86_android_tablet_get_gpiod() to no longer use
gpiolib private functions like gpiochip_find().

As a bonus this allows specifying that the GPIO is active-low,
like the /CE (charge enable) pin on the bq25892 charger on
the Lenovo Yoga Tablet 3.

Reported-by: Bartosz Golaszewski <brgl@bgdev.pl>
Closes: https://lore.kernel.org/platform-driver-x86/20230905185309.131295-12-brgl@bgdev.pl/
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Link: https://lore.kernel.org/r/20230909141816.58358-7-hdegoede@redhat.com
drivers/platform/x86/x86-android-tablets/asus.c
drivers/platform/x86/x86-android-tablets/core.c
drivers/platform/x86/x86-android-tablets/lenovo.c
drivers/platform/x86/x86-android-tablets/other.c
drivers/platform/x86/x86-android-tablets/x86-android-tablets.h

index f9c4083be86d8bd27109bead0b1b90a875b41eac..227afbb51078625f2948f24ffb4640bb81418544 100644 (file)
@@ -303,6 +303,7 @@ static const struct x86_i2c_client_info asus_tf103c_i2c_clients[] __initconst =
                        .index = 28,
                        .trigger = ACPI_EDGE_SENSITIVE,
                        .polarity = ACPI_ACTIVE_LOW,
+                       .con_id = "atmel_mxt_ts_irq",
                },
        },
 };
index 654cc8c0a1275326be053570a7041c8459749b3c..eb62db606925d4382732b9ef537c8260a364e1a2 100644 (file)
@@ -12,7 +12,7 @@
 
 #include <linux/acpi.h>
 #include <linux/dmi.h>
-#include <linux/gpio/driver.h>
+#include <linux/gpio/consumer.h>
 #include <linux/gpio/machine.h>
 #include <linux/irq.h>
 #include <linux/module.h>
 #include <linux/string.h>
 
 #include "x86-android-tablets.h"
-/* For gpiochip_get_desc() which is EXPORT_SYMBOL_GPL() */
-#include "../../../gpio/gpiolib.h"
-#include "../../../gpio/gpiolib-acpi.h"
 
 static struct platform_device *x86_android_tablet_device;
 
-static int gpiochip_find_match_label(struct gpio_chip *gc, void *data)
-{
-       return gc->label && !strcmp(gc->label, data);
-}
-
-int x86_android_tablet_get_gpiod(const char *label, int pin, struct gpio_desc **desc)
+int x86_android_tablet_get_gpiod(const char *chip, int pin, const char *con_id,
+                                bool active_low, enum gpiod_flags dflags,
+                                struct gpio_desc **desc)
 {
+       struct gpiod_lookup_table *lookup;
        struct gpio_desc *gpiod;
-       struct gpio_chip *chip;
 
-       chip = gpiochip_find((void *)label, gpiochip_find_match_label);
-       if (!chip) {
-               pr_err("error cannot find GPIO chip %s\n", label);
-               return -ENODEV;
-       }
+       lookup = kzalloc(struct_size(lookup, table, 2), GFP_KERNEL);
+       if (!lookup)
+               return -ENOMEM;
+
+       lookup->dev_id = KBUILD_MODNAME;
+       lookup->table[0].key = chip;
+       lookup->table[0].chip_hwnum = pin;
+       lookup->table[0].con_id = con_id;
+       lookup->table[0].flags = active_low ? GPIO_ACTIVE_LOW : GPIO_ACTIVE_HIGH;
+
+       gpiod_add_lookup_table(lookup);
+       gpiod = devm_gpiod_get(&x86_android_tablet_device->dev, con_id, dflags);
+       gpiod_remove_lookup_table(lookup);
+       kfree(lookup);
 
-       gpiod = gpiochip_get_desc(chip, pin);
        if (IS_ERR(gpiod)) {
-               pr_err("error %ld getting GPIO %s %d\n", PTR_ERR(gpiod), label, pin);
+               pr_err("error %ld getting GPIO %s %d\n", PTR_ERR(gpiod), chip, pin);
                return PTR_ERR(gpiod);
        }
 
-       *desc = gpiod;
+       if (desc)
+               *desc = gpiod;
+
        return 0;
 }
 
@@ -79,7 +83,8 @@ int x86_acpi_irq_helper_get(const struct x86_acpi_irq_data *data)
                return irq;
        case X86_ACPI_IRQ_TYPE_GPIOINT:
                /* Like acpi_dev_gpio_irq_get(), but without parsing ACPI resources */
-               ret = x86_android_tablet_get_gpiod(data->chip, data->index, &gpiod);
+               ret = x86_android_tablet_get_gpiod(data->chip, data->index, data->con_id,
+                                                  false, GPIOD_ASIS, &gpiod);
                if (ret)
                        return ret;
 
@@ -356,7 +361,9 @@ static __init int x86_android_tablet_probe(struct platform_device *pdev)
 
                for (i = 0; i < dev_info->gpio_button_count; i++) {
                        ret = x86_android_tablet_get_gpiod(dev_info->gpio_button[i].chip,
-                                                          dev_info->gpio_button[i].pin, &gpiod);
+                                                          dev_info->gpio_button[i].pin,
+                                                          dev_info->gpio_button[i].button.desc,
+                                                          false, GPIOD_IN, &gpiod);
                        if (ret < 0) {
                                x86_android_tablet_remove(pdev);
                                return ret;
@@ -364,6 +371,8 @@ static __init int x86_android_tablet_probe(struct platform_device *pdev)
 
                        buttons[i] = dev_info->gpio_button[i].button;
                        buttons[i].gpio = desc_to_gpio(gpiod);
+                       /* Release gpiod so that gpio-keys can request it */
+                       devm_gpiod_put(&x86_android_tablet_device->dev, gpiod);
                }
 
                pdata.buttons = buttons;
index 26a4ef670ad7ca424fda9efb38e4e4b89f01ecbe..35aa2968d7264165b497fee5d0e71d55e475bee4 100644 (file)
@@ -95,6 +95,7 @@ static const struct x86_i2c_client_info lenovo_yb1_x90_i2c_clients[] __initconst
                        .index = 56,
                        .trigger = ACPI_EDGE_SENSITIVE,
                        .polarity = ACPI_ACTIVE_LOW,
+                       .con_id = "goodix_ts_irq",
                },
        }, {
                /* Wacom Digitizer in keyboard half */
@@ -111,6 +112,7 @@ static const struct x86_i2c_client_info lenovo_yb1_x90_i2c_clients[] __initconst
                        .index = 49,
                        .trigger = ACPI_LEVEL_SENSITIVE,
                        .polarity = ACPI_ACTIVE_LOW,
+                       .con_id = "wacom_irq",
                },
        }, {
                /* LP8557 Backlight controller */
@@ -136,6 +138,7 @@ static const struct x86_i2c_client_info lenovo_yb1_x90_i2c_clients[] __initconst
                        .index = 77,
                        .trigger = ACPI_LEVEL_SENSITIVE,
                        .polarity = ACPI_ACTIVE_LOW,
+                       .con_id = "hideep_ts_irq",
                },
        },
 };
@@ -321,6 +324,7 @@ static struct x86_i2c_client_info lenovo_yoga_tab2_830_1050_i2c_clients[] __init
                        .index = 2,
                        .trigger = ACPI_EDGE_SENSITIVE,
                        .polarity = ACPI_ACTIVE_HIGH,
+                       .con_id = "bq24292i_irq",
                },
        }, {
                /* BQ27541 fuel-gauge */
@@ -431,7 +435,8 @@ static int __init lenovo_yoga_tab2_830_1050_init_touchscreen(void)
        int ret;
 
        /* Use PMIC GPIO 10 bootstrap pin to differentiate 830 vs 1050 */
-       ret = x86_android_tablet_get_gpiod("gpio_crystalcove", 10, &gpiod);
+       ret = x86_android_tablet_get_gpiod("gpio_crystalcove", 10, "yoga_bootstrap",
+                                          false, GPIOD_IN, &gpiod);
        if (ret)
                return ret;
 
@@ -615,6 +620,7 @@ static const struct x86_i2c_client_info lenovo_yt3_i2c_clients[] __initconst = {
                        .index = 5,
                        .trigger = ACPI_EDGE_SENSITIVE,
                        .polarity = ACPI_ACTIVE_LOW,
+                       .con_id = "bq25892_0_irq",
                },
        }, {
                /* bq27500 fuel-gauge for the round li-ion cells in the hinge */
@@ -640,6 +646,7 @@ static const struct x86_i2c_client_info lenovo_yt3_i2c_clients[] __initconst = {
                        .index = 77,
                        .trigger = ACPI_LEVEL_SENSITIVE,
                        .polarity = ACPI_ACTIVE_LOW,
+                       .con_id = "hideep_ts_irq",
                },
        }, {
                /* LP8557 Backlight controller */
@@ -655,7 +662,6 @@ static const struct x86_i2c_client_info lenovo_yt3_i2c_clients[] __initconst = {
 
 static int __init lenovo_yt3_init(void)
 {
-       struct gpio_desc *gpiod;
        int ret;
 
        /*
@@ -665,31 +671,23 @@ static int __init lenovo_yt3_init(void)
         *
         * The bq25890_charger driver controls these through I2C, but this only
         * works if not overridden by the pins. Set these pins here:
-        * 1. Set /CE to 0 to allow charging.
+        * 1. Set /CE to 1 to allow charging.
         * 2. Set OTG to 0 disable V5 boost output since the 5V boost output of
         *    the main "bq25892_1" charger is used when necessary.
         */
 
        /* /CE pin */
-       ret = x86_android_tablet_get_gpiod("INT33FF:02", 22, &gpiod);
+       ret = x86_android_tablet_get_gpiod("INT33FF:02", 22, "bq25892_0_ce",
+                                          true, GPIOD_OUT_HIGH, NULL);
        if (ret < 0)
                return ret;
 
-       /*
-        * The gpio_desc returned by x86_android_tablet_get_gpiod() is a "raw"
-        * gpio_desc, that is there is no way to pass lookup-flags like
-        * GPIO_ACTIVE_LOW. Set the GPIO to 0 here to enable charging since
-        * the /CE pin is active-low, but not marked as such in the gpio_desc.
-        */
-       gpiod_set_value(gpiod, 0);
-
        /* OTG pin */
-       ret = x86_android_tablet_get_gpiod("INT33FF:03", 19, &gpiod);
+       ret = x86_android_tablet_get_gpiod("INT33FF:03", 19, "bq25892_0_otg",
+                                          false, GPIOD_OUT_LOW, NULL);
        if (ret < 0)
                return ret;
 
-       gpiod_set_value(gpiod, 0);
-
        /* Enable the regulators used by the touchscreen */
        intel_soc_pmic_exec_mipi_pmic_seq_element(0x6e, 0x9b, 0x02, 0xff);
        intel_soc_pmic_exec_mipi_pmic_seq_element(0x6e, 0xa0, 0x02, 0xff);
index 621ca1e54d1fe5549585d3fcab8b1c468627507e..bc6bbf7ec6ea137101394b59d38fb7471675b00c 100644 (file)
@@ -47,6 +47,7 @@ static const struct x86_i2c_client_info acer_b1_750_i2c_clients[] __initconst =
                        .index = 3,
                        .trigger = ACPI_EDGE_SENSITIVE,
                        .polarity = ACPI_ACTIVE_LOW,
+                       .con_id = "NVT-ts_irq",
                },
        }, {
                /* BMA250E accelerometer */
@@ -62,6 +63,7 @@ static const struct x86_i2c_client_info acer_b1_750_i2c_clients[] __initconst =
                        .index = 25,
                        .trigger = ACPI_LEVEL_SENSITIVE,
                        .polarity = ACPI_ACTIVE_HIGH,
+                       .con_id = "bma250e_irq",
                },
        },
 };
@@ -174,6 +176,7 @@ static const struct x86_i2c_client_info chuwi_hi8_i2c_clients[] __initconst = {
                        .index = 23,
                        .trigger = ACPI_LEVEL_SENSITIVE,
                        .polarity = ACPI_ACTIVE_HIGH,
+                       .con_id = "bma250e_irq",
                },
        },
 };
@@ -312,6 +315,7 @@ static const struct x86_i2c_client_info medion_lifetab_s10346_i2c_clients[] __in
                        .index = 23,
                        .trigger = ACPI_EDGE_SENSITIVE,
                        .polarity = ACPI_ACTIVE_HIGH,
+                       .con_id = "kxtj21009_irq",
                },
        }, {
                /* goodix touchscreen */
@@ -402,6 +406,7 @@ static const struct x86_i2c_client_info nextbook_ares8_i2c_clients[] __initconst
                        .index = 3,
                        .trigger = ACPI_EDGE_SENSITIVE,
                        .polarity = ACPI_ACTIVE_LOW,
+                       .con_id = "ft5416_irq",
                },
        },
 };
@@ -460,6 +465,7 @@ static const struct x86_i2c_client_info nextbook_ares8a_i2c_clients[] __initcons
                        .index = 17,
                        .trigger = ACPI_EDGE_SENSITIVE,
                        .polarity = ACPI_ACTIVE_LOW,
+                       .con_id = "ft5416_irq",
                },
        },
 };
index bf97fb84c0d4a17d38b4bfc1e2cffedbb6009088..9d2fb7fded6d766a55d90e3b409e46d6b84189cd 100644 (file)
@@ -10,6 +10,7 @@
 #ifndef __PDX86_X86_ANDROID_TABLETS_H
 #define __PDX86_X86_ANDROID_TABLETS_H
 
+#include <linux/gpio/consumer.h>
 #include <linux/gpio_keys.h>
 #include <linux/i2c.h>
 #include <linux/irqdomain_defs.h>
@@ -37,6 +38,7 @@ struct x86_acpi_irq_data {
        int index;
        int trigger;  /* ACPI_EDGE_SENSITIVE / ACPI_LEVEL_SENSITIVE */
        int polarity; /* ACPI_ACTIVE_HIGH / ACPI_ACTIVE_LOW / ACPI_ACTIVE_BOTH */
+       const char *con_id;
 };
 
 /* Structs to describe devices to instantiate */
@@ -81,7 +83,9 @@ struct x86_dev_info {
        void (*exit)(void);
 };
 
-int x86_android_tablet_get_gpiod(const char *label, int pin, struct gpio_desc **desc);
+int x86_android_tablet_get_gpiod(const char *chip, int pin, const char *con_id,
+                                bool active_low, enum gpiod_flags dflags,
+                                struct gpio_desc **desc);
 int x86_acpi_irq_helper_get(const struct x86_acpi_irq_data *data);
 
 /*