on fedora 33,with kernel 5.10.2 , i use this patch ,then touchpad work!
diff -Narup a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c
--- a/drivers/gpio/gpiolib-acpi.c 2020-12-14 06:41:30.000000000 +0800
+++ b/drivers/gpio/gpiolib-acpi.c 2020-12-22 14:31:53.078877803 +0800
@@ -205,6 +205,68 @@ static void acpi_gpiochip_request_irqs(s
acpi_gpiochip_request_irq(acpi_gpio, event);
}
+static enum gpiod_flags
+acpi_gpio_to_gpiod_flags(const struct acpi_resource_gpio *agpio, int polarity)
+{
+ /* GpioInt() implies input configuration */
+ if (agpio->connection_type == ACPI_RESOURCE_GPIO_TYPE_INT)
+ return GPIOD_IN;
+
+ switch (agpio->io_restriction) {
+ case ACPI_IO_RESTRICT_INPUT:
+ return GPIOD_IN;
+ case ACPI_IO_RESTRICT_OUTPUT:
+ /*
+ * ACPI GPIO resources don't contain an initial value for the
+ * GPIO. Therefore we deduce that value from the pull field
+ * and the polarity instead. If the pin is pulled up we assume
+ * default to be high, if it is pulled down we assume default
+ * to be low, otherwise we leave pin untouched. For active low
+ * polarity values will be switched. See also
+ * Documentation/firmware-guide/acpi/gpio-properties.rst.
+ */
+ switch (agpio->pin_config) {
+ case ACPI_PIN_CONFIG_PULLUP:
+ return polarity == GPIO_ACTIVE_LOW ? GPIOD_OUT_LOW :
GPIOD_OUT_HIGH;
+ case ACPI_PIN_CONFIG_PULLDOWN:
+ return polarity == GPIO_ACTIVE_LOW ? GPIOD_OUT_HIGH :
GPIOD_OUT_LOW;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ /*
+ * Assume that the BIOS has configured the direction and pull
+ * accordingly.
+ */
+ return GPIOD_ASIS;
+}
+
+static struct gpio_desc *acpi_request_own_gpiod(struct gpio_chip *chip,
+ struct acpi_resource_gpio
*agpio,
+ unsigned int index,
+ const char *label)
+{
+ int polarity = GPIO_ACTIVE_HIGH;
+ enum gpiod_flags flags = acpi_gpio_to_gpiod_flags(agpio, polarity);
+ unsigned int pin = agpio->pin_table[index];
+ struct gpio_desc *desc;
+ int ret;
+
+ desc = gpiochip_request_own_desc(chip, pin, label, polarity, flags);
+ if (IS_ERR(desc))
+ return desc;
+
+ ret = gpio_set_debounce_timeout(desc, agpio->debounce_timeout);
+ if (ret)
+ gpiochip_free_own_desc(desc);
+
+ return ret ? ERR_PTR(ret) : desc;
+}
+
static bool acpi_gpio_in_ignore_list(const char *controller_in, int pin_in)
{
const char *controller, *pin_str;
@@ -290,8 +352,8 @@ static acpi_status acpi_gpiochip_alloc_e
if (!handler)
return AE_OK;
- desc = gpiochip_request_own_desc(chip, pin, "ACPI:Event",
- GPIO_ACTIVE_HIGH, GPIOD_IN);
+ desc = acpi_request_own_gpiod(chip, agpio, 0, "ACPI:Event");
+
if (IS_ERR(desc)) {
dev_err(chip->parent,
"Failed to request GPIO for pin 0x%04X, err %ld\n",
@@ -526,39 +588,6 @@ static bool acpi_get_driver_gpio_data(st
return false;
}
-static enum gpiod_flags
-acpi_gpio_to_gpiod_flags(const struct acpi_resource_gpio *agpio)
-{
- switch (agpio->io_restriction) {
- case ACPI_IO_RESTRICT_INPUT:
- return GPIOD_IN;
- case ACPI_IO_RESTRICT_OUTPUT:
- /*
- * ACPI GPIO resources don't contain an initial value for the
- * GPIO. Therefore we deduce that value from the pull field
- * instead. If the pin is pulled up we assume default to be
- * high, if it is pulled down we assume default to be low,
- * otherwise we leave pin untouched.
- */
- switch (agpio->pin_config) {
- case ACPI_PIN_CONFIG_PULLUP:
- return GPIOD_OUT_HIGH;
- case ACPI_PIN_CONFIG_PULLDOWN:
- return GPIOD_OUT_LOW;
- default:
- break;
- }
- default:
- break;
- }
-
- /*
- * Assume that the BIOS has configured the direction and pull
- * accordingly.
- */
- return GPIOD_ASIS;
-}
-
static int
__acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags, enum gpiod_flags
update)
{
@@ -664,6 +693,7 @@ static int acpi_populate_gpio_lookup(str
lookup->desc = acpi_get_gpiod(agpio->resource_source.string_ptr,
agpio->pin_table[pin_index]);
lookup->info.pin_config = agpio->pin_config;
+ lookup->info.debounce = agpio->debounce_timeout;
lookup->info.gpioint = gpioint;
/*
@@ -674,13 +704,13 @@ static int acpi_populate_gpio_lookup(str
* - ACPI_ACTIVE_HIGH == GPIO_ACTIVE_HIGH
*/
if (lookup->info.gpioint) {
- lookup->info.flags = GPIOD_IN;
lookup->info.polarity = agpio->polarity;
lookup->info.triggering = agpio->triggering;
} else {
- lookup->info.flags = acpi_gpio_to_gpiod_flags(agpio);
lookup->info.polarity = lookup->active_low;
}
+
+ lookup->info.flags = acpi_gpio_to_gpiod_flags(agpio,
lookup->info.polarity);
}
return 1;
@@ -942,6 +972,7 @@ int acpi_dev_gpio_irq_get(struct acpi_de
if (info.gpioint && idx++ == index) {
unsigned long lflags = GPIO_LOOKUP_FLAGS_DEFAULT;
+ enum gpiod_flags dflags = GPIOD_ASIS;
char label[32];
int irq;
@@ -951,12 +982,19 @@ int acpi_dev_gpio_irq_get(struct acpi_de
irq = gpiod_to_irq(desc);
if (irq < 0)
return irq;
+
+ acpi_gpio_update_gpiod_flags(&dflags, &info);
+ acpi_gpio_update_gpiod_lookup_flags(&lflags, &info);
snprintf(label, sizeof(label), "GpioInt() %d", index);
- ret = gpiod_configure_flags(desc, label, lflags,
info.flags);
+ ret = gpiod_configure_flags(desc, label, lflags,
dflags);
if (ret < 0)
return ret;
+ ret = gpio_set_debounce_timeout(desc, info.debounce);
+ if (ret)
+ return ret;
+
irq_flags = acpi_dev_get_irq_type(info.triggering,
info.polarity);
@@ -979,7 +1017,7 @@ acpi_gpio_adr_space_handler(u32 function
void *region_context)
{
struct acpi_gpio_chip *achip = region_context;
- struct gpio_chip *chip = achip->chip;
+ //struct gpio_chip *chip = achip->chip;
struct acpi_resource_gpio *agpio;
struct acpi_resource *ares;
int pin_index = (int)address;
@@ -1042,23 +1080,20 @@ acpi_gpio_adr_space_handler(u32 function
}
if (!found) {
- enum gpiod_flags flags =
acpi_gpio_to_gpiod_flags(agpio);
- const char *label = "ACPI:OpRegion";
- desc = gpiochip_request_own_desc(chip, pin, label,
- GPIO_ACTIVE_HIGH,
- flags);
if (IS_ERR(desc)) {
- status = AE_ERROR;
+
mutex_unlock(&achip->conn_lock);
+ status = AE_ERROR;
goto out;
}
conn = kzalloc(sizeof(*conn), GFP_KERNEL);
if (!conn) {
- status = AE_NO_MEMORY;
+
gpiochip_free_own_desc(desc);
mutex_unlock(&achip->conn_lock);
+ status = AE_NO_MEMORY;
goto out;
}
@@ -1070,8 +1105,7 @@ acpi_gpio_adr_space_handler(u32 function
mutex_unlock(&achip->conn_lock);
if (function == ACPI_WRITE)
- gpiod_set_raw_value_cansleep(desc,
- !!((1 << i) & *value));
+ gpiod_set_raw_value_cansleep(desc, !!(*value & BIT(i)));
else
*value |= (u64)gpiod_get_raw_value_cansleep(desc) << i;
}
@@ -1132,7 +1166,7 @@ acpi_gpiochip_parse_own_gpio(struct acpi
int ret;
*lflags = GPIO_LOOKUP_FLAGS_DEFAULT;
- *dflags = 0;
+ *dflags = GPIOD_ASIS;
*name = NULL;
ret = fwnode_property_read_u32_array(fwnode, "gpios", gpios,
diff -Narup a/drivers/gpio/gpiolib-acpi.h b/drivers/gpio/gpiolib-acpi.h
--- a/drivers/gpio/gpiolib-acpi.h 2020-12-14 06:41:30.000000000 +0800
+++ b/drivers/gpio/gpiolib-acpi.h 2020-12-22 13:45:48.396976098 +0800
@@ -18,6 +18,7 @@ struct acpi_device;
* @pin_config: pin bias as provided by ACPI
* @polarity: interrupt polarity as provided by ACPI
* @triggering: triggering type as provided by ACPI
+ * @debounce: debounce timeout as provided by ACPI
* @quirks: Linux specific quirks as provided by struct acpi_gpio_mapping
*/
struct acpi_gpio_info {
@@ -27,6 +28,7 @@ struct acpi_gpio_info {
int pin_config;
int polarity;
int triggering;
+ unsigned int debounce;
unsigned int quirks;
};
diff -Narup a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
--- a/drivers/gpio/gpiolib.c 2020-12-14 06:41:30.000000000 +0800
+++ b/drivers/gpio/gpiolib.c 2020-12-22 14:28:08.770149915 +0800
@@ -1477,7 +1477,8 @@ static void gpiochip_set_irq_hooks(struc
if (WARN_ON(gc->irq.irq_enable))
return;
/* Check if the irqchip already has this hook... */
- if (irqchip->irq_enable == gpiochip_irq_enable) {
+ if (irqchip->irq_enable == gpiochip_irq_enable ||
+ irqchip->irq_mask == gpiochip_irq_mask) {
/*
* ...and if so, give a gentle warning that this is bad
* practice.
@@ -1985,11 +1986,9 @@ static int gpiod_request_commit(struct g
if (test_and_set_bit(FLAG_REQUESTED, &desc->flags) == 0) {
desc_set_label(desc, label ? : "?");
- ret = 0;
} else {
- kfree_const(label);
ret = -EBUSY;
- goto done;
+ goto out_free_unlock;
}
if (gc->request) {
@@ -2002,11 +2001,10 @@ static int gpiod_request_commit(struct g
ret = -EINVAL;
spin_lock_irqsave(&gpio_lock, flags);
- if (ret < 0) {
+ if (ret) {
desc_set_label(desc, NULL);
- kfree_const(label);
clear_bit(FLAG_REQUESTED, &desc->flags);
- goto done;
+ goto out_free_unlock;
}
}
if (gc->get_direction) {
@@ -2015,8 +2013,13 @@ static int gpiod_request_commit(struct g
gpiod_get_direction(desc);
spin_lock_irqsave(&gpio_lock, flags);
}
-done:
+
+ spin_unlock_irqrestore(&gpio_lock, flags);
+ return 0;
+
+out_free_unlock:
spin_unlock_irqrestore(&gpio_lock, flags);
+ kfree_const(label);
return ret;
}
@@ -2068,7 +2071,7 @@ int gpiod_request(struct gpio_desc *desc
if (try_module_get(gdev->owner)) {
ret = gpiod_request_commit(desc, label);
- if (ret < 0)
+ if (ret)
module_put(gdev->owner);
else
get_device(&gdev->dev);
@@ -2251,30 +2254,49 @@ static int gpio_do_set_config(struct gpi
return gc->set_config(gc, offset, config);
}
-static int gpio_set_config(struct gpio_desc *desc, enum pin_config_param mode)
+static int gpio_set_config_with_argument(struct gpio_desc *desc,
+ enum pin_config_param mode,
+ u32 argument)
{
struct gpio_chip *gc = desc->gdev->chip;
unsigned long config;
- unsigned arg;
+
+ config = pinconf_to_config_packed(mode, argument);
+ return gpio_do_set_config(gc, gpio_chip_hwgpio(desc), config);
+}
+
+static int gpio_set_config_with_argument_optional(struct gpio_desc *desc,
+ enum pin_config_param mode,
+ u32 argument)
+{
+ struct device *dev = &desc->gdev->dev;
+ int gpio = gpio_chip_hwgpio(desc);
+ int ret;
+
+ ret = gpio_set_config_with_argument(desc, mode, argument);
+ if (ret != -ENOTSUPP)
+ return ret;
switch (mode) {
- case PIN_CONFIG_BIAS_PULL_DOWN:
- case PIN_CONFIG_BIAS_PULL_UP:
- arg = 1;
+ case PIN_CONFIG_PERSIST_STATE:
+ dev_dbg(dev, "Persistence not supported for GPIO %d\n", gpio);
break;
-
default:
- arg = 0;
+ break;
}
- config = PIN_CONF_PACKED(mode, arg);
- return gpio_do_set_config(gc, gpio_chip_hwgpio(desc), config);
+ return 0;
+}
+
+static int gpio_set_config(struct gpio_desc *desc, enum pin_config_param mode)
+{
+ return gpio_set_config_with_argument(desc, mode, 0);
}
static int gpio_set_bias(struct gpio_desc *desc)
{
- int bias = 0;
- int ret = 0;
+ enum pin_config_param bias;
+ unsigned int arg;
if (test_bit(FLAG_BIAS_DISABLE, &desc->flags))
bias = PIN_CONFIG_BIAS_DISABLE;
@@ -2282,13 +2304,28 @@ static int gpio_set_bias(struct gpio_des
bias = PIN_CONFIG_BIAS_PULL_UP;
else if (test_bit(FLAG_PULL_DOWN, &desc->flags))
bias = PIN_CONFIG_BIAS_PULL_DOWN;
+ else
+ return 0;
- if (bias) {
- ret = gpio_set_config(desc, bias);
- if (ret != -ENOTSUPP)
- return ret;
+ switch (bias) {
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ case PIN_CONFIG_BIAS_PULL_UP:
+ arg = 1;
+ break;
+
+ default:
+ arg = 0;
+ break;
}
- return 0;
+
+ return gpio_set_config_with_argument_optional(desc, bias, arg);
+}
+
+int gpio_set_debounce_timeout(struct gpio_desc *desc, unsigned int debounce)
+{
+ return gpio_set_config_with_argument_optional(desc,
+ PIN_CONFIG_INPUT_DEBOUNCE,
+ debounce);
}
/**
@@ -2529,11 +2566,6 @@ EXPORT_SYMBOL_GPL(gpiod_set_debounce);
*/
int gpiod_set_transitory(struct gpio_desc *desc, bool transitory)
{
- struct gpio_chip *gc;
- unsigned long packed;
- int gpio;
- int rc;
-
VALIDATE_DESC(desc);
/*
* Handle FLAG_TRANSITORY first, enabling queries to gpiolib for
@@ -2542,21 +2574,9 @@ int gpiod_set_transitory(struct gpio_des
assign_bit(FLAG_TRANSITORY, &desc->flags, transitory);
/* If the driver supports it, set the persistence state now */
- gc = desc->gdev->chip;
- if (!gc->set_config)
- return 0;
-
- packed = pinconf_to_config_packed(PIN_CONFIG_PERSIST_STATE,
- !transitory);
- gpio = gpio_chip_hwgpio(desc);
- rc = gpio_do_set_config(gc, gpio, packed);
- if (rc == -ENOTSUPP) {
- dev_dbg(&desc->gdev->dev, "Persistence not supported for GPIO
%d\n",
- gpio);
- return 0;
- }
-
- return rc;
+ return gpio_set_config_with_argument_optional(desc,
+ PIN_CONFIG_PERSIST_STATE,
+ !transitory);
}
EXPORT_SYMBOL_GPL(gpiod_set_transitory);
@@ -3784,7 +3804,7 @@ struct gpio_desc *fwnode_gpiod_get_index
desc = fwnode_get_named_gpiod(fwnode, prop_name, index, flags,
label);
- if (!IS_ERR(desc) || (PTR_ERR(desc) != -ENOENT))
+ if (!gpiod_not_found(desc))
break;
}
@@ -3960,7 +3980,7 @@ struct gpio_desc *__must_check gpiod_get
* Either we are not using DT or ACPI, or their lookup did not return
* a result. In that case, use platform lookup as a fallback.
*/
- if (!desc || desc == ERR_PTR(-ENOENT)) {
+ if (!desc || gpiod_not_found(desc)) {
dev_dbg(dev, "using lookup tables for GPIO lookup\n");
desc = gpiod_find(dev, con_id, idx, &lookupflags);
}
@@ -3975,7 +3995,7 @@ struct gpio_desc *__must_check gpiod_get
* the device name as label
*/
ret = gpiod_request(desc, con_id ? con_id : devname);
- if (ret < 0) {
+ if (ret ) {
if (ret == -EBUSY && flags & GPIOD_FLAGS_BIT_NONEXCLUSIVE) {
/*
* This happens when there are several consumers for
@@ -4095,10 +4115,8 @@ struct gpio_desc *__must_check gpiod_get
struct gpio_desc *desc;
desc = gpiod_get_index(dev, con_id, index, flags);
- if (IS_ERR(desc)) {
- if (PTR_ERR(desc) == -ENOENT)
- return NULL;
- }
+ if (gpiod_not_found(desc))
+ return NULL;
return desc;
}
@@ -4300,7 +4318,7 @@ struct gpio_descs *__must_check gpiod_ge
struct gpio_descs *descs;
descs = gpiod_get_array(dev, con_id, flags);
- if (PTR_ERR(descs) == -ENOENT)
+ if (gpiod_not_found(descs))
return NULL;
return descs;
diff -Narup a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h
--- a/drivers/gpio/gpiolib.h 2020-12-14 06:41:30.000000000 +0800
+++ b/drivers/gpio/gpiolib.h 2020-12-22 14:05:04.658807802 +0800
@@ -116,6 +116,7 @@ struct gpio_desc {
#define FLAG_BIAS_DISABLE 15 /* GPIO has pull disabled */
#define FLAG_EDGE_RISING 16 /* GPIO CDEV detects rising edge events
*/
#define FLAG_EDGE_FALLING 17 /* GPIO CDEV detects falling edge
events */
+#define FLAG_EVENT_CLOCK_REALTIME 18 /* GPIO CDEV reports REALTIME
timestamps in events */
/* Connection label */
const char *label;
@@ -130,10 +131,13 @@ struct gpio_desc {
#endif
};
+#define gpiod_not_found(desc) (IS_ERR(desc) && PTR_ERR(desc) ==
-ENOENT)
+
int gpiod_request(struct gpio_desc *desc, const char *label);
void gpiod_free(struct gpio_desc *desc);
int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id,
unsigned long lflags, enum gpiod_flags dflags);
+int gpio_set_debounce_timeout(struct gpio_desc *desc, unsigned int debounce);
int gpiod_hog(struct gpio_desc *desc, const char *name,
unsigned long lflags, enum gpiod_flags dflags);
--
You received this bug notification because you are a member of Ubuntu
Bugs, which is subscribed to Ubuntu.
https://bugs.launchpad.net/bugs/1887190
Title:
MSFT Touchpad not working on Lenovo Legion-5 15ARH05
To manage notifications about this bug go to:
https://bugs.launchpad.net/pop-os/+bug/1887190/+subscriptions
--
ubuntu-bugs mailing list
[email protected]
https://lists.ubuntu.com/mailman/listinfo/ubuntu-bugs