platform/x86: x86-android-tablets: Stop using gpiolib private APIs
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
This commit is contained in:
parent
8b57d33a6f
commit
4014ae236b
5 changed files with 55 additions and 37 deletions
|
@ -303,6 +303,7 @@ static const struct x86_i2c_client_info asus_tf103c_i2c_clients[] __initconst =
|
||||||
.index = 28,
|
.index = 28,
|
||||||
.trigger = ACPI_EDGE_SENSITIVE,
|
.trigger = ACPI_EDGE_SENSITIVE,
|
||||||
.polarity = ACPI_ACTIVE_LOW,
|
.polarity = ACPI_ACTIVE_LOW,
|
||||||
|
.con_id = "atmel_mxt_ts_irq",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
#include <linux/acpi.h>
|
#include <linux/acpi.h>
|
||||||
#include <linux/dmi.h>
|
#include <linux/dmi.h>
|
||||||
#include <linux/gpio/driver.h>
|
#include <linux/gpio/consumer.h>
|
||||||
#include <linux/gpio/machine.h>
|
#include <linux/gpio/machine.h>
|
||||||
#include <linux/irq.h>
|
#include <linux/irq.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
@ -21,35 +21,39 @@
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
|
|
||||||
#include "x86-android-tablets.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 struct platform_device *x86_android_tablet_device;
|
||||||
|
|
||||||
static int gpiochip_find_match_label(struct gpio_chip *gc, void *data)
|
int x86_android_tablet_get_gpiod(const char *chip, int pin, const char *con_id,
|
||||||
{
|
bool active_low, enum gpiod_flags dflags,
|
||||||
return gc->label && !strcmp(gc->label, data);
|
struct gpio_desc **desc)
|
||||||
}
|
|
||||||
|
|
||||||
int x86_android_tablet_get_gpiod(const char *label, int pin, struct gpio_desc **desc)
|
|
||||||
{
|
{
|
||||||
|
struct gpiod_lookup_table *lookup;
|
||||||
struct gpio_desc *gpiod;
|
struct gpio_desc *gpiod;
|
||||||
struct gpio_chip *chip;
|
|
||||||
|
|
||||||
chip = gpiochip_find((void *)label, gpiochip_find_match_label);
|
lookup = kzalloc(struct_size(lookup, table, 2), GFP_KERNEL);
|
||||||
if (!chip) {
|
if (!lookup)
|
||||||
pr_err("error cannot find GPIO chip %s\n", label);
|
return -ENOMEM;
|
||||||
return -ENODEV;
|
|
||||||
}
|
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)) {
|
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);
|
return PTR_ERR(gpiod);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (desc)
|
||||||
*desc = gpiod;
|
*desc = gpiod;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,7 +83,8 @@ int x86_acpi_irq_helper_get(const struct x86_acpi_irq_data *data)
|
||||||
return irq;
|
return irq;
|
||||||
case X86_ACPI_IRQ_TYPE_GPIOINT:
|
case X86_ACPI_IRQ_TYPE_GPIOINT:
|
||||||
/* Like acpi_dev_gpio_irq_get(), but without parsing ACPI resources */
|
/* 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)
|
if (ret)
|
||||||
return 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++) {
|
for (i = 0; i < dev_info->gpio_button_count; i++) {
|
||||||
ret = x86_android_tablet_get_gpiod(dev_info->gpio_button[i].chip,
|
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) {
|
if (ret < 0) {
|
||||||
x86_android_tablet_remove(pdev);
|
x86_android_tablet_remove(pdev);
|
||||||
return ret;
|
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] = dev_info->gpio_button[i].button;
|
||||||
buttons[i].gpio = desc_to_gpio(gpiod);
|
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;
|
pdata.buttons = buttons;
|
||||||
|
|
|
@ -95,6 +95,7 @@ static const struct x86_i2c_client_info lenovo_yb1_x90_i2c_clients[] __initconst
|
||||||
.index = 56,
|
.index = 56,
|
||||||
.trigger = ACPI_EDGE_SENSITIVE,
|
.trigger = ACPI_EDGE_SENSITIVE,
|
||||||
.polarity = ACPI_ACTIVE_LOW,
|
.polarity = ACPI_ACTIVE_LOW,
|
||||||
|
.con_id = "goodix_ts_irq",
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
/* Wacom Digitizer in keyboard half */
|
/* Wacom Digitizer in keyboard half */
|
||||||
|
@ -111,6 +112,7 @@ static const struct x86_i2c_client_info lenovo_yb1_x90_i2c_clients[] __initconst
|
||||||
.index = 49,
|
.index = 49,
|
||||||
.trigger = ACPI_LEVEL_SENSITIVE,
|
.trigger = ACPI_LEVEL_SENSITIVE,
|
||||||
.polarity = ACPI_ACTIVE_LOW,
|
.polarity = ACPI_ACTIVE_LOW,
|
||||||
|
.con_id = "wacom_irq",
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
/* LP8557 Backlight controller */
|
/* LP8557 Backlight controller */
|
||||||
|
@ -136,6 +138,7 @@ static const struct x86_i2c_client_info lenovo_yb1_x90_i2c_clients[] __initconst
|
||||||
.index = 77,
|
.index = 77,
|
||||||
.trigger = ACPI_LEVEL_SENSITIVE,
|
.trigger = ACPI_LEVEL_SENSITIVE,
|
||||||
.polarity = ACPI_ACTIVE_LOW,
|
.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,
|
.index = 2,
|
||||||
.trigger = ACPI_EDGE_SENSITIVE,
|
.trigger = ACPI_EDGE_SENSITIVE,
|
||||||
.polarity = ACPI_ACTIVE_HIGH,
|
.polarity = ACPI_ACTIVE_HIGH,
|
||||||
|
.con_id = "bq24292i_irq",
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
/* BQ27541 fuel-gauge */
|
/* BQ27541 fuel-gauge */
|
||||||
|
@ -431,7 +435,8 @@ static int __init lenovo_yoga_tab2_830_1050_init_touchscreen(void)
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* Use PMIC GPIO 10 bootstrap pin to differentiate 830 vs 1050 */
|
/* 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)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@ -615,6 +620,7 @@ static const struct x86_i2c_client_info lenovo_yt3_i2c_clients[] __initconst = {
|
||||||
.index = 5,
|
.index = 5,
|
||||||
.trigger = ACPI_EDGE_SENSITIVE,
|
.trigger = ACPI_EDGE_SENSITIVE,
|
||||||
.polarity = ACPI_ACTIVE_LOW,
|
.polarity = ACPI_ACTIVE_LOW,
|
||||||
|
.con_id = "bq25892_0_irq",
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
/* bq27500 fuel-gauge for the round li-ion cells in the hinge */
|
/* 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,
|
.index = 77,
|
||||||
.trigger = ACPI_LEVEL_SENSITIVE,
|
.trigger = ACPI_LEVEL_SENSITIVE,
|
||||||
.polarity = ACPI_ACTIVE_LOW,
|
.polarity = ACPI_ACTIVE_LOW,
|
||||||
|
.con_id = "hideep_ts_irq",
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
/* LP8557 Backlight controller */
|
/* 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)
|
static int __init lenovo_yt3_init(void)
|
||||||
{
|
{
|
||||||
struct gpio_desc *gpiod;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -665,31 +671,23 @@ static int __init lenovo_yt3_init(void)
|
||||||
*
|
*
|
||||||
* The bq25890_charger driver controls these through I2C, but this only
|
* The bq25890_charger driver controls these through I2C, but this only
|
||||||
* works if not overridden by the pins. Set these pins here:
|
* 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
|
* 2. Set OTG to 0 disable V5 boost output since the 5V boost output of
|
||||||
* the main "bq25892_1" charger is used when necessary.
|
* the main "bq25892_1" charger is used when necessary.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* /CE pin */
|
/* /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)
|
if (ret < 0)
|
||||||
return ret;
|
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 */
|
/* 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)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
gpiod_set_value(gpiod, 0);
|
|
||||||
|
|
||||||
/* Enable the regulators used by the touchscreen */
|
/* 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, 0x9b, 0x02, 0xff);
|
||||||
intel_soc_pmic_exec_mipi_pmic_seq_element(0x6e, 0xa0, 0x02, 0xff);
|
intel_soc_pmic_exec_mipi_pmic_seq_element(0x6e, 0xa0, 0x02, 0xff);
|
||||||
|
|
|
@ -47,6 +47,7 @@ static const struct x86_i2c_client_info acer_b1_750_i2c_clients[] __initconst =
|
||||||
.index = 3,
|
.index = 3,
|
||||||
.trigger = ACPI_EDGE_SENSITIVE,
|
.trigger = ACPI_EDGE_SENSITIVE,
|
||||||
.polarity = ACPI_ACTIVE_LOW,
|
.polarity = ACPI_ACTIVE_LOW,
|
||||||
|
.con_id = "NVT-ts_irq",
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
/* BMA250E accelerometer */
|
/* BMA250E accelerometer */
|
||||||
|
@ -62,6 +63,7 @@ static const struct x86_i2c_client_info acer_b1_750_i2c_clients[] __initconst =
|
||||||
.index = 25,
|
.index = 25,
|
||||||
.trigger = ACPI_LEVEL_SENSITIVE,
|
.trigger = ACPI_LEVEL_SENSITIVE,
|
||||||
.polarity = ACPI_ACTIVE_HIGH,
|
.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,
|
.index = 23,
|
||||||
.trigger = ACPI_LEVEL_SENSITIVE,
|
.trigger = ACPI_LEVEL_SENSITIVE,
|
||||||
.polarity = ACPI_ACTIVE_HIGH,
|
.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,
|
.index = 23,
|
||||||
.trigger = ACPI_EDGE_SENSITIVE,
|
.trigger = ACPI_EDGE_SENSITIVE,
|
||||||
.polarity = ACPI_ACTIVE_HIGH,
|
.polarity = ACPI_ACTIVE_HIGH,
|
||||||
|
.con_id = "kxtj21009_irq",
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
/* goodix touchscreen */
|
/* goodix touchscreen */
|
||||||
|
@ -402,6 +406,7 @@ static const struct x86_i2c_client_info nextbook_ares8_i2c_clients[] __initconst
|
||||||
.index = 3,
|
.index = 3,
|
||||||
.trigger = ACPI_EDGE_SENSITIVE,
|
.trigger = ACPI_EDGE_SENSITIVE,
|
||||||
.polarity = ACPI_ACTIVE_LOW,
|
.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,
|
.index = 17,
|
||||||
.trigger = ACPI_EDGE_SENSITIVE,
|
.trigger = ACPI_EDGE_SENSITIVE,
|
||||||
.polarity = ACPI_ACTIVE_LOW,
|
.polarity = ACPI_ACTIVE_LOW,
|
||||||
|
.con_id = "ft5416_irq",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#ifndef __PDX86_X86_ANDROID_TABLETS_H
|
#ifndef __PDX86_X86_ANDROID_TABLETS_H
|
||||||
#define __PDX86_X86_ANDROID_TABLETS_H
|
#define __PDX86_X86_ANDROID_TABLETS_H
|
||||||
|
|
||||||
|
#include <linux/gpio/consumer.h>
|
||||||
#include <linux/gpio_keys.h>
|
#include <linux/gpio_keys.h>
|
||||||
#include <linux/i2c.h>
|
#include <linux/i2c.h>
|
||||||
#include <linux/irqdomain_defs.h>
|
#include <linux/irqdomain_defs.h>
|
||||||
|
@ -37,6 +38,7 @@ struct x86_acpi_irq_data {
|
||||||
int index;
|
int index;
|
||||||
int trigger; /* ACPI_EDGE_SENSITIVE / ACPI_LEVEL_SENSITIVE */
|
int trigger; /* ACPI_EDGE_SENSITIVE / ACPI_LEVEL_SENSITIVE */
|
||||||
int polarity; /* ACPI_ACTIVE_HIGH / ACPI_ACTIVE_LOW / ACPI_ACTIVE_BOTH */
|
int polarity; /* ACPI_ACTIVE_HIGH / ACPI_ACTIVE_LOW / ACPI_ACTIVE_BOTH */
|
||||||
|
const char *con_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Structs to describe devices to instantiate */
|
/* Structs to describe devices to instantiate */
|
||||||
|
@ -81,7 +83,9 @@ struct x86_dev_info {
|
||||||
void (*exit)(void);
|
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);
|
int x86_acpi_irq_helper_get(const struct x86_acpi_irq_data *data);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Add table
Reference in a new issue