From 85c675d0d09a45a135bddd15d7b385f8758c32fb Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 18 May 2024 19:35:05 +0200 Subject: Adding upstream version 6.7.7. Signed-off-by: Daniel Baumann --- drivers/gpio/gpio-pca953x.c | 305 ++++++++++++++++++++------------------------ 1 file changed, 136 insertions(+), 169 deletions(-) (limited to 'drivers/gpio/gpio-pca953x.c') diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index bdd50a78e4..00ffa168e4 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -8,22 +8,30 @@ * Derived from drivers/i2c/chips/pca9539.c */ -#include +#include #include -#include -#include +#include +#include +#include #include #include #include +#include +#include #include -#include -#include +#include +#include #include #include #include #include -#include +#include +#include + +#include + +#include #define PCA953X_INPUT 0x00 #define PCA953X_OUTPUT 0x01 @@ -118,6 +126,7 @@ MODULE_DEVICE_TABLE(i2c, pca953x_id); #ifdef CONFIG_GPIO_PCA953X_IRQ +#include #include static const struct acpi_gpio_params pca953x_irq_gpios = { 0, 0, true }; @@ -211,7 +220,6 @@ struct pca953x_chip { struct i2c_client *client; struct gpio_chip gpio_chip; - const char *const *names; unsigned long driver_data; struct regulator *regulator; @@ -414,7 +422,7 @@ static const struct regmap_config pca953x_i2c_regmap = { .volatile_reg = pca953x_volatile_register, .disable_locking = true, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, .max_register = 0x7f, }; @@ -430,7 +438,7 @@ static const struct regmap_config pca953x_ai_i2c_regmap = { .volatile_reg = pca953x_volatile_register, .disable_locking = true, - .cache_type = REGCACHE_RBTREE, + .cache_type = REGCACHE_MAPLE, .max_register = 0x7f, }; @@ -520,12 +528,10 @@ static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off) struct pca953x_chip *chip = gpiochip_get_data(gc); u8 dirreg = chip->recalc_addr(chip, chip->regs->direction, off); u8 bit = BIT(off % BANK_SZ); - int ret; - mutex_lock(&chip->i2c_lock); - ret = regmap_write_bits(chip->regmap, dirreg, bit, bit); - mutex_unlock(&chip->i2c_lock); - return ret; + guard(mutex)(&chip->i2c_lock); + + return regmap_write_bits(chip->regmap, dirreg, bit, bit); } static int pca953x_gpio_direction_output(struct gpio_chip *gc, @@ -537,17 +543,15 @@ static int pca953x_gpio_direction_output(struct gpio_chip *gc, u8 bit = BIT(off % BANK_SZ); int ret; - mutex_lock(&chip->i2c_lock); + guard(mutex)(&chip->i2c_lock); + /* set output level */ ret = regmap_write_bits(chip->regmap, outreg, bit, val ? bit : 0); if (ret) - goto exit; + return ret; /* then direction */ - ret = regmap_write_bits(chip->regmap, dirreg, bit, 0); -exit: - mutex_unlock(&chip->i2c_lock); - return ret; + return regmap_write_bits(chip->regmap, dirreg, bit, 0); } static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off) @@ -558,9 +562,8 @@ static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off) u32 reg_val; int ret; - mutex_lock(&chip->i2c_lock); - ret = regmap_read(chip->regmap, inreg, ®_val); - mutex_unlock(&chip->i2c_lock); + scoped_guard(mutex, &chip->i2c_lock) + ret = regmap_read(chip->regmap, inreg, ®_val); if (ret < 0) return ret; @@ -573,9 +576,9 @@ static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val) u8 outreg = chip->recalc_addr(chip, chip->regs->output, off); u8 bit = BIT(off % BANK_SZ); - mutex_lock(&chip->i2c_lock); + guard(mutex)(&chip->i2c_lock); + regmap_write_bits(chip->regmap, outreg, bit, val ? bit : 0); - mutex_unlock(&chip->i2c_lock); } static int pca953x_gpio_get_direction(struct gpio_chip *gc, unsigned off) @@ -586,9 +589,8 @@ static int pca953x_gpio_get_direction(struct gpio_chip *gc, unsigned off) u32 reg_val; int ret; - mutex_lock(&chip->i2c_lock); - ret = regmap_read(chip->regmap, dirreg, ®_val); - mutex_unlock(&chip->i2c_lock); + scoped_guard(mutex, &chip->i2c_lock) + ret = regmap_read(chip->regmap, dirreg, ®_val); if (ret < 0) return ret; @@ -605,9 +607,8 @@ static int pca953x_gpio_get_multiple(struct gpio_chip *gc, DECLARE_BITMAP(reg_val, MAX_LINE); int ret; - mutex_lock(&chip->i2c_lock); - ret = pca953x_read_regs(chip, chip->regs->input, reg_val); - mutex_unlock(&chip->i2c_lock); + scoped_guard(mutex, &chip->i2c_lock) + ret = pca953x_read_regs(chip, chip->regs->input, reg_val); if (ret) return ret; @@ -622,16 +623,15 @@ static void pca953x_gpio_set_multiple(struct gpio_chip *gc, DECLARE_BITMAP(reg_val, MAX_LINE); int ret; - mutex_lock(&chip->i2c_lock); + guard(mutex)(&chip->i2c_lock); + ret = pca953x_read_regs(chip, chip->regs->output, reg_val); if (ret) - goto exit; + return; bitmap_replace(reg_val, reg_val, bits, mask, gc->ngpio); pca953x_write_regs(chip, chip->regs->output, reg_val); -exit: - mutex_unlock(&chip->i2c_lock); } static int pca953x_gpio_set_pull_up_down(struct pca953x_chip *chip, @@ -639,7 +639,6 @@ static int pca953x_gpio_set_pull_up_down(struct pca953x_chip *chip, unsigned long config) { enum pin_config_param param = pinconf_to_config_param(config); - u8 pull_en_reg = chip->recalc_addr(chip, PCAL953X_PULL_EN, offset); u8 pull_sel_reg = chip->recalc_addr(chip, PCAL953X_PULL_SEL, offset); u8 bit = BIT(offset % BANK_SZ); @@ -652,7 +651,7 @@ static int pca953x_gpio_set_pull_up_down(struct pca953x_chip *chip, if (!(chip->driver_data & PCA_PCAL)) return -ENOTSUPP; - mutex_lock(&chip->i2c_lock); + guard(mutex)(&chip->i2c_lock); /* Configure pull-up/pull-down */ if (param == PIN_CONFIG_BIAS_PULL_UP) @@ -662,17 +661,13 @@ static int pca953x_gpio_set_pull_up_down(struct pca953x_chip *chip, else ret = 0; if (ret) - goto exit; + return ret; /* Disable/Enable pull-up/pull-down */ if (param == PIN_CONFIG_BIAS_DISABLE) - ret = regmap_write_bits(chip->regmap, pull_en_reg, bit, 0); + return regmap_write_bits(chip->regmap, pull_en_reg, bit, 0); else - ret = regmap_write_bits(chip->regmap, pull_en_reg, bit, bit); - -exit: - mutex_unlock(&chip->i2c_lock); - return ret; + return regmap_write_bits(chip->regmap, pull_en_reg, bit, bit); } static int pca953x_gpio_set_config(struct gpio_chip *gc, unsigned int offset, @@ -693,9 +688,7 @@ static int pca953x_gpio_set_config(struct gpio_chip *gc, unsigned int offset, static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios) { - struct gpio_chip *gc; - - gc = &chip->gpio_chip; + struct gpio_chip *gc = &chip->gpio_chip; gc->direction_input = pca953x_gpio_direction_input; gc->direction_output = pca953x_gpio_direction_output; @@ -712,7 +705,6 @@ static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios) gc->label = dev_name(&chip->client->dev); gc->parent = &chip->client->dev; gc->owner = THIS_MODULE; - gc->names = chip->names; } #ifdef CONFIG_GPIO_PCA953X_IRQ @@ -793,11 +785,11 @@ static int pca953x_irq_set_type(struct irq_data *d, unsigned int type) { struct gpio_chip *gc = irq_data_get_irq_chip_data(d); struct pca953x_chip *chip = gpiochip_get_data(gc); + struct device *dev = &chip->client->dev; irq_hw_number_t hwirq = irqd_to_hwirq(d); if (!(type & IRQ_TYPE_EDGE_BOTH)) { - dev_err(&chip->client->dev, "irq %d: unsupported type %d\n", - d->irq, type); + dev_err(dev, "irq %d: unsupported type %d\n", d->irq, type); return -EINVAL; } @@ -902,10 +894,8 @@ static irqreturn_t pca953x_irq_handler(int irq, void *devid) bitmap_zero(pending, MAX_LINE); - mutex_lock(&chip->i2c_lock); - ret = pca953x_irq_pending(chip, pending); - mutex_unlock(&chip->i2c_lock); - + scoped_guard(mutex, &chip->i2c_lock) + ret = pca953x_irq_pending(chip, pending); if (ret) { ret = 0; @@ -928,13 +918,15 @@ static irqreturn_t pca953x_irq_handler(int irq, void *devid) static int pca953x_irq_setup(struct pca953x_chip *chip, int irq_base) { struct i2c_client *client = chip->client; + struct device *dev = &client->dev; DECLARE_BITMAP(reg_direction, MAX_LINE); DECLARE_BITMAP(irq_stat, MAX_LINE); + struct gpio_chip *gc = &chip->gpio_chip; struct gpio_irq_chip *girq; int ret; if (dmi_first_match(pca953x_dmi_acpi_irq_info)) { - ret = pca953x_acpi_get_irq(&client->dev); + ret = pca953x_acpi_get_irq(dev); if (ret > 0) client->irq = ret; } @@ -958,7 +950,7 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, int irq_base) * this purpose. */ pca953x_read_regs(chip, chip->regs->direction, reg_direction); - bitmap_and(chip->irq_stat, irq_stat, reg_direction, chip->gpio_chip.ngpio); + bitmap_and(chip->irq_stat, irq_stat, reg_direction, gc->ngpio); mutex_init(&chip->irq_lock); girq = &chip->gpio_chip.irq; @@ -972,33 +964,29 @@ static int pca953x_irq_setup(struct pca953x_chip *chip, int irq_base) girq->threaded = true; girq->first = irq_base; /* FIXME: get rid of this */ - ret = devm_request_threaded_irq(&client->dev, client->irq, - NULL, pca953x_irq_handler, - IRQF_ONESHOT | IRQF_SHARED, - dev_name(&client->dev), chip); - if (ret) { - dev_err(&client->dev, "failed to request irq %d\n", - client->irq); - return ret; - } + ret = devm_request_threaded_irq(dev, client->irq, NULL, pca953x_irq_handler, + IRQF_ONESHOT | IRQF_SHARED, dev_name(dev), + chip); + if (ret) + return dev_err_probe(dev, client->irq, "failed to request irq\n"); return 0; } #else /* CONFIG_GPIO_PCA953X_IRQ */ -static int pca953x_irq_setup(struct pca953x_chip *chip, - int irq_base) +static int pca953x_irq_setup(struct pca953x_chip *chip, int irq_base) { struct i2c_client *client = chip->client; + struct device *dev = &client->dev; if (client->irq && irq_base != -1 && (chip->driver_data & PCA_INT)) - dev_warn(&client->dev, "interrupt support not compiled in\n"); + dev_warn(dev, "interrupt support not compiled in\n"); return 0; } #endif -static int device_pca95xx_init(struct pca953x_chip *chip, u32 invert) +static int device_pca95xx_init(struct pca953x_chip *chip) { DECLARE_BITMAP(val, MAX_LINE); u8 regaddr; @@ -1008,68 +996,81 @@ static int device_pca95xx_init(struct pca953x_chip *chip, u32 invert) ret = regcache_sync_region(chip->regmap, regaddr, regaddr + NBANK(chip) - 1); if (ret) - goto out; + return ret; regaddr = chip->recalc_addr(chip, chip->regs->direction, 0); ret = regcache_sync_region(chip->regmap, regaddr, regaddr + NBANK(chip) - 1); if (ret) - goto out; + return ret; - /* set platform specific polarity inversion */ - if (invert) - bitmap_fill(val, MAX_LINE); - else - bitmap_zero(val, MAX_LINE); + /* clear polarity inversion */ + bitmap_zero(val, MAX_LINE); - ret = pca953x_write_regs(chip, chip->regs->invert, val); -out: - return ret; + return pca953x_write_regs(chip, chip->regs->invert, val); } -static int device_pca957x_init(struct pca953x_chip *chip, u32 invert) +static int device_pca957x_init(struct pca953x_chip *chip) { DECLARE_BITMAP(val, MAX_LINE); unsigned int i; int ret; - ret = device_pca95xx_init(chip, invert); + ret = device_pca95xx_init(chip); if (ret) - goto out; + return ret; /* To enable register 6, 7 to control pull up and pull down */ for (i = 0; i < NBANK(chip); i++) bitmap_set_value8(val, 0x02, i * BANK_SZ); - ret = pca953x_write_regs(chip, PCA957X_BKEN, val); + return pca953x_write_regs(chip, PCA957X_BKEN, val); +} + +static void pca953x_disable_regulator(void *reg) +{ + regulator_disable(reg); +} + +static int pca953x_get_and_enable_regulator(struct pca953x_chip *chip) +{ + struct device *dev = &chip->client->dev; + struct regulator *reg = chip->regulator; + int ret; + + reg = devm_regulator_get(dev, "vcc"); + if (IS_ERR(reg)) + return dev_err_probe(dev, PTR_ERR(reg), "reg get err\n"); + + ret = regulator_enable(reg); if (ret) - goto out; + return dev_err_probe(dev, ret, "reg en err\n"); + ret = devm_add_action_or_reset(dev, pca953x_disable_regulator, reg); + if (ret) + return ret; + + chip->regulator = reg; return 0; -out: - return ret; } static int pca953x_probe(struct i2c_client *client) { + struct device *dev = &client->dev; struct pca953x_platform_data *pdata; struct pca953x_chip *chip; - int irq_base = 0; + int irq_base; int ret; - u32 invert = 0; - struct regulator *reg; const struct regmap_config *regmap_config; - chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); + chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL); if (chip == NULL) return -ENOMEM; - pdata = dev_get_platdata(&client->dev); + pdata = dev_get_platdata(dev); if (pdata) { irq_base = pdata->irq_base; chip->gpio_start = pdata->gpio_base; - invert = pdata->invert; - chip->names = pdata->names; } else { struct gpio_desc *reset_gpio; @@ -1083,8 +1084,7 @@ static int pca953x_probe(struct i2c_client *client) * using "reset" GPIO. Otherwise any of those platform * must use _DSD method with corresponding property. */ - reset_gpio = devm_gpiod_get_optional(&client->dev, "reset", - GPIOD_OUT_LOW); + reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); if (IS_ERR(reset_gpio)) return PTR_ERR(reset_gpio); } @@ -1094,26 +1094,19 @@ static int pca953x_probe(struct i2c_client *client) if (!chip->driver_data) return -ENODEV; - reg = devm_regulator_get(&client->dev, "vcc"); - if (IS_ERR(reg)) - return dev_err_probe(&client->dev, PTR_ERR(reg), "reg get err\n"); - - ret = regulator_enable(reg); - if (ret) { - dev_err(&client->dev, "reg en err: %d\n", ret); + ret = pca953x_get_and_enable_regulator(chip); + if (ret) return ret; - } - chip->regulator = reg; i2c_set_clientdata(client, chip); pca953x_setup_gpio(chip, chip->driver_data & PCA_GPIO_MASK); if (NBANK(chip) > 2 || PCA_CHIP_TYPE(chip->driver_data) == PCA957X_TYPE) { - dev_info(&client->dev, "using AI\n"); + dev_info(dev, "using AI\n"); regmap_config = &pca953x_ai_i2c_regmap; } else { - dev_info(&client->dev, "using no AI\n"); + dev_info(dev, "using no AI\n"); regmap_config = &pca953x_i2c_regmap; } @@ -1126,10 +1119,8 @@ static int pca953x_probe(struct i2c_client *client) } chip->regmap = devm_regmap_init_i2c(client, regmap_config); - if (IS_ERR(chip->regmap)) { - ret = PTR_ERR(chip->regmap); - goto err_exit; - } + if (IS_ERR(chip->regmap)) + return PTR_ERR(chip->regmap); regcache_mark_dirty(chip->regmap); @@ -1158,53 +1149,24 @@ static int pca953x_probe(struct i2c_client *client) */ if (PCA_CHIP_TYPE(chip->driver_data) == PCA957X_TYPE) { chip->regs = &pca957x_regs; - ret = device_pca957x_init(chip, invert); + ret = device_pca957x_init(chip); } else { chip->regs = &pca953x_regs; - ret = device_pca95xx_init(chip, invert); + ret = device_pca95xx_init(chip); } if (ret) - goto err_exit; + return ret; ret = pca953x_irq_setup(chip, irq_base); if (ret) - goto err_exit; - - ret = devm_gpiochip_add_data(&client->dev, &chip->gpio_chip, chip); - if (ret) - goto err_exit; - - if (pdata && pdata->setup) { - ret = pdata->setup(client, chip->gpio_chip.base, - chip->gpio_chip.ngpio, pdata->context); - if (ret < 0) - dev_warn(&client->dev, "setup failed, %d\n", ret); - } - - return 0; - -err_exit: - regulator_disable(chip->regulator); - return ret; -} - -static void pca953x_remove(struct i2c_client *client) -{ - struct pca953x_platform_data *pdata = dev_get_platdata(&client->dev); - struct pca953x_chip *chip = i2c_get_clientdata(client); - - if (pdata && pdata->teardown) { - pdata->teardown(client, chip->gpio_chip.base, - chip->gpio_chip.ngpio, pdata->context); - } + return ret; - regulator_disable(chip->regulator); + return devm_gpiochip_add_data(dev, &chip->gpio_chip, chip); } -#ifdef CONFIG_PM_SLEEP -static int pca953x_regcache_sync(struct device *dev) +static int pca953x_regcache_sync(struct pca953x_chip *chip) { - struct pca953x_chip *chip = dev_get_drvdata(dev); + struct device *dev = &chip->client->dev; int ret; u8 regaddr; @@ -1251,13 +1213,32 @@ static int pca953x_regcache_sync(struct device *dev) return 0; } +static int pca953x_restore_context(struct pca953x_chip *chip) +{ + int ret; + + guard(mutex)(&chip->i2c_lock); + + regcache_cache_only(chip->regmap, false); + regcache_mark_dirty(chip->regmap); + ret = pca953x_regcache_sync(chip); + if (ret) + return ret; + + return regcache_sync(chip->regmap); +} + +static void pca953x_save_context(struct pca953x_chip *chip) +{ + guard(mutex)(&chip->i2c_lock); + regcache_cache_only(chip->regmap, true); +} + static int pca953x_suspend(struct device *dev) { struct pca953x_chip *chip = dev_get_drvdata(dev); - mutex_lock(&chip->i2c_lock); - regcache_cache_only(chip->regmap, true); - mutex_unlock(&chip->i2c_lock); + pca953x_save_context(chip); if (atomic_read(&chip->wakeup_path)) device_set_wakeup_path(dev); @@ -1280,25 +1261,14 @@ static int pca953x_resume(struct device *dev) } } - mutex_lock(&chip->i2c_lock); - regcache_cache_only(chip->regmap, false); - regcache_mark_dirty(chip->regmap); - ret = pca953x_regcache_sync(dev); - if (ret) { - mutex_unlock(&chip->i2c_lock); - return ret; - } - - ret = regcache_sync(chip->regmap); - mutex_unlock(&chip->i2c_lock); - if (ret) { + ret = pca953x_restore_context(chip); + if (ret) dev_err(dev, "Failed to restore register map: %d\n", ret); - return ret; - } - return 0; + return ret; } -#endif + +static DEFINE_SIMPLE_DEV_PM_OPS(pca953x_pm_ops, pca953x_suspend, pca953x_resume); /* convenience to stop overlong match-table lines */ #define OF_653X(__nrgpio, __int) ((void *)(__nrgpio | PCAL653X_TYPE | __int)) @@ -1356,17 +1326,14 @@ static const struct of_device_id pca953x_dt_ids[] = { MODULE_DEVICE_TABLE(of, pca953x_dt_ids); -static SIMPLE_DEV_PM_OPS(pca953x_pm_ops, pca953x_suspend, pca953x_resume); - static struct i2c_driver pca953x_driver = { .driver = { .name = "pca953x", - .pm = &pca953x_pm_ops, + .pm = pm_sleep_ptr(&pca953x_pm_ops), .of_match_table = pca953x_dt_ids, .acpi_match_table = pca953x_acpi_ids, }, .probe = pca953x_probe, - .remove = pca953x_remove, .id_table = pca953x_id, }; -- cgit v1.2.3