mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-16 09:32:36 -04:00
Merge tag 'gpio-fixes-for-v6.18-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux
Pull gpio fixes from Bartosz Golaszewski: - fix regressions in regmap cache initialization in gpio-104-idio-16 and gpio-pci-idio-16 - configure first 16 GPIO lines of the IDIO-16 as fixed outputs - fix duplicated IRQ mapping that can lead to an RCU stall in gpio-ljca - fix printf formatters passed to dev_err() and make failure to set debounce period non fatal * tag 'gpio-fixes-for-v6.18-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux: gpio: ljca: Fix duplicated IRQ mapping gpiolib: acpi: Use %pe when passing an error pointer to dev_err() gpiolib: acpi: Make set debounce errors non fatal gpio: idio-16: Define fixed direction of the GPIO lines gpio: regmap: add the .fixed_direction_output configuration parameter gpio: pci-idio-16: Define maximum valid register address offset gpio: 104-idio-16: Define maximum valid register address offset
This commit is contained in:
@@ -59,6 +59,7 @@ static const struct regmap_config idio_16_regmap_config = {
|
||||
.reg_stride = 1,
|
||||
.val_bits = 8,
|
||||
.io_port = true,
|
||||
.max_register = 0x5,
|
||||
.wr_table = &idio_16_wr_table,
|
||||
.rd_table = &idio_16_rd_table,
|
||||
.volatile_table = &idio_16_rd_table,
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#define DEFAULT_SYMBOL_NAMESPACE "GPIO_IDIO_16"
|
||||
|
||||
#include <linux/bitmap.h>
|
||||
#include <linux/bits.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
@@ -107,6 +108,7 @@ int devm_idio_16_regmap_register(struct device *const dev,
|
||||
struct idio_16_data *data;
|
||||
struct regmap_irq_chip *chip;
|
||||
struct regmap_irq_chip_data *chip_data;
|
||||
DECLARE_BITMAP(fixed_direction_output, IDIO_16_NGPIO);
|
||||
|
||||
if (!config->parent)
|
||||
return -EINVAL;
|
||||
@@ -164,6 +166,9 @@ int devm_idio_16_regmap_register(struct device *const dev,
|
||||
gpio_config.irq_domain = regmap_irq_get_domain(chip_data);
|
||||
gpio_config.reg_mask_xlate = idio_16_reg_mask_xlate;
|
||||
|
||||
bitmap_from_u64(fixed_direction_output, GENMASK_U64(15, 0));
|
||||
gpio_config.fixed_direction_output = fixed_direction_output;
|
||||
|
||||
return PTR_ERR_OR_ZERO(devm_gpio_regmap_register(dev, &gpio_config));
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_idio_16_regmap_register);
|
||||
|
||||
@@ -286,22 +286,14 @@ static void ljca_gpio_event_cb(void *context, u8 cmd, const void *evt_data,
|
||||
{
|
||||
const struct ljca_gpio_packet *packet = evt_data;
|
||||
struct ljca_gpio_dev *ljca_gpio = context;
|
||||
int i, irq;
|
||||
int i;
|
||||
|
||||
if (cmd != LJCA_GPIO_INT_EVENT)
|
||||
return;
|
||||
|
||||
for (i = 0; i < packet->num; i++) {
|
||||
irq = irq_find_mapping(ljca_gpio->gc.irq.domain,
|
||||
packet->item[i].index);
|
||||
if (!irq) {
|
||||
dev_err(ljca_gpio->gc.parent,
|
||||
"gpio_id %u does not mapped to IRQ yet\n",
|
||||
packet->item[i].index);
|
||||
return;
|
||||
}
|
||||
|
||||
generic_handle_domain_irq(ljca_gpio->gc.irq.domain, irq);
|
||||
generic_handle_domain_irq(ljca_gpio->gc.irq.domain,
|
||||
packet->item[i].index);
|
||||
set_bit(packet->item[i].index, ljca_gpio->reenable_irqs);
|
||||
}
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ static const struct regmap_config idio_16_regmap_config = {
|
||||
.reg_stride = 1,
|
||||
.val_bits = 8,
|
||||
.io_port = true,
|
||||
.max_register = 0x7,
|
||||
.wr_table = &idio_16_wr_table,
|
||||
.rd_table = &idio_16_rd_table,
|
||||
.volatile_table = &idio_16_rd_table,
|
||||
|
||||
@@ -31,6 +31,7 @@ struct gpio_regmap {
|
||||
unsigned int reg_clr_base;
|
||||
unsigned int reg_dir_in_base;
|
||||
unsigned int reg_dir_out_base;
|
||||
unsigned long *fixed_direction_output;
|
||||
|
||||
#ifdef CONFIG_REGMAP_IRQ
|
||||
int regmap_irq_line;
|
||||
@@ -134,6 +135,13 @@ static int gpio_regmap_get_direction(struct gpio_chip *chip,
|
||||
unsigned int base, val, reg, mask;
|
||||
int invert, ret;
|
||||
|
||||
if (gpio->fixed_direction_output) {
|
||||
if (test_bit(offset, gpio->fixed_direction_output))
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
else
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
}
|
||||
|
||||
if (gpio->reg_dat_base && !gpio->reg_set_base)
|
||||
return GPIO_LINE_DIRECTION_IN;
|
||||
if (gpio->reg_set_base && !gpio->reg_dat_base)
|
||||
@@ -284,6 +292,17 @@ struct gpio_regmap *gpio_regmap_register(const struct gpio_regmap_config *config
|
||||
goto err_free_gpio;
|
||||
}
|
||||
|
||||
if (config->fixed_direction_output) {
|
||||
gpio->fixed_direction_output = bitmap_alloc(chip->ngpio,
|
||||
GFP_KERNEL);
|
||||
if (!gpio->fixed_direction_output) {
|
||||
ret = -ENOMEM;
|
||||
goto err_free_gpio;
|
||||
}
|
||||
bitmap_copy(gpio->fixed_direction_output,
|
||||
config->fixed_direction_output, chip->ngpio);
|
||||
}
|
||||
|
||||
/* if not set, assume there is only one register */
|
||||
gpio->ngpio_per_reg = config->ngpio_per_reg;
|
||||
if (!gpio->ngpio_per_reg)
|
||||
@@ -300,7 +319,7 @@ struct gpio_regmap *gpio_regmap_register(const struct gpio_regmap_config *config
|
||||
|
||||
ret = gpiochip_add_data(chip, gpio);
|
||||
if (ret < 0)
|
||||
goto err_free_gpio;
|
||||
goto err_free_bitmap;
|
||||
|
||||
#ifdef CONFIG_REGMAP_IRQ
|
||||
if (config->regmap_irq_chip) {
|
||||
@@ -309,7 +328,7 @@ struct gpio_regmap *gpio_regmap_register(const struct gpio_regmap_config *config
|
||||
config->regmap_irq_line, config->regmap_irq_flags,
|
||||
0, config->regmap_irq_chip, &gpio->irq_chip_data);
|
||||
if (ret)
|
||||
goto err_free_gpio;
|
||||
goto err_free_bitmap;
|
||||
|
||||
irq_domain = regmap_irq_get_domain(gpio->irq_chip_data);
|
||||
} else
|
||||
@@ -326,6 +345,8 @@ struct gpio_regmap *gpio_regmap_register(const struct gpio_regmap_config *config
|
||||
|
||||
err_remove_gpiochip:
|
||||
gpiochip_remove(chip);
|
||||
err_free_bitmap:
|
||||
bitmap_free(gpio->fixed_direction_output);
|
||||
err_free_gpio:
|
||||
kfree(gpio);
|
||||
return ERR_PTR(ret);
|
||||
@@ -344,6 +365,7 @@ void gpio_regmap_unregister(struct gpio_regmap *gpio)
|
||||
#endif
|
||||
|
||||
gpiochip_remove(&gpio->gpio_chip);
|
||||
bitmap_free(gpio->fixed_direction_output);
|
||||
kfree(gpio);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gpio_regmap_unregister);
|
||||
|
||||
@@ -291,6 +291,19 @@ acpi_gpio_to_gpiod_flags(const struct acpi_resource_gpio *agpio, int polarity)
|
||||
return GPIOD_ASIS;
|
||||
}
|
||||
|
||||
static void acpi_gpio_set_debounce_timeout(struct gpio_desc *desc,
|
||||
unsigned int acpi_debounce)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* ACPI uses hundredths of milliseconds units */
|
||||
acpi_debounce *= 10;
|
||||
ret = gpio_set_debounce_timeout(desc, acpi_debounce);
|
||||
if (ret)
|
||||
gpiod_warn(desc, "Failed to set debounce-timeout %u: %d\n",
|
||||
acpi_debounce, ret);
|
||||
}
|
||||
|
||||
static struct gpio_desc *acpi_request_own_gpiod(struct gpio_chip *chip,
|
||||
struct acpi_resource_gpio *agpio,
|
||||
unsigned int index,
|
||||
@@ -300,18 +313,12 @@ static struct gpio_desc *acpi_request_own_gpiod(struct gpio_chip *chip,
|
||||
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;
|
||||
|
||||
/* ACPI uses hundredths of milliseconds units */
|
||||
ret = gpio_set_debounce_timeout(desc, agpio->debounce_timeout * 10);
|
||||
if (ret)
|
||||
dev_warn(chip->parent,
|
||||
"Failed to set debounce-timeout for pin 0x%04X, err %d\n",
|
||||
pin, ret);
|
||||
acpi_gpio_set_debounce_timeout(desc, agpio->debounce_timeout);
|
||||
|
||||
return desc;
|
||||
}
|
||||
@@ -375,8 +382,8 @@ static acpi_status acpi_gpiochip_alloc_event(struct acpi_resource *ares,
|
||||
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",
|
||||
pin, PTR_ERR(desc));
|
||||
"Failed to request GPIO for pin 0x%04X, err %pe\n",
|
||||
pin, desc);
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
@@ -944,7 +951,6 @@ struct gpio_desc *acpi_find_gpio(struct fwnode_handle *fwnode,
|
||||
bool can_fallback = acpi_can_fallback_to_crs(adev, con_id);
|
||||
struct acpi_gpio_info info = {};
|
||||
struct gpio_desc *desc;
|
||||
int ret;
|
||||
|
||||
desc = __acpi_find_gpio(fwnode, con_id, idx, can_fallback, &info);
|
||||
if (IS_ERR(desc))
|
||||
@@ -959,10 +965,7 @@ struct gpio_desc *acpi_find_gpio(struct fwnode_handle *fwnode,
|
||||
acpi_gpio_update_gpiod_flags(dflags, &info);
|
||||
acpi_gpio_update_gpiod_lookup_flags(lookupflags, &info);
|
||||
|
||||
/* ACPI uses hundredths of milliseconds units */
|
||||
ret = gpio_set_debounce_timeout(desc, info.debounce * 10);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
acpi_gpio_set_debounce_timeout(desc, info.debounce);
|
||||
|
||||
return desc;
|
||||
}
|
||||
|
||||
@@ -38,6 +38,10 @@ struct regmap;
|
||||
* offset to a register/bitmask pair. If not
|
||||
* given the default gpio_regmap_simple_xlate()
|
||||
* is used.
|
||||
* @fixed_direction_output:
|
||||
* (Optional) Bitmap representing the fixed direction of
|
||||
* the GPIO lines. Useful when there are GPIO lines with a
|
||||
* fixed direction mixed together in the same register.
|
||||
* @drvdata: (Optional) Pointer to driver specific data which is
|
||||
* not used by gpio-remap but is provided "as is" to the
|
||||
* driver callback(s).
|
||||
@@ -85,6 +89,7 @@ struct gpio_regmap_config {
|
||||
int reg_stride;
|
||||
int ngpio_per_reg;
|
||||
struct irq_domain *irq_domain;
|
||||
unsigned long *fixed_direction_output;
|
||||
|
||||
#ifdef CONFIG_REGMAP_IRQ
|
||||
struct regmap_irq_chip *regmap_irq_chip;
|
||||
|
||||
Reference in New Issue
Block a user