Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

gpio: adp5585: support gpi events

Add support for adding GPIs to the event FIFO. This is done by adding
irq_chip support. Like this, one can use the input gpio_keys driver as a
"frontend" device and input handler.

As part of this change, we now implement .request() and .free() as we can't
blindly consume all available pins as GPIOs (example: some pins can be
used for forming a keymap matrix).

Also note that the number of pins can now be obtained from the parent,
top level device. Hence the 'max_gpio' variable can be removed.

Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Acked-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Signed-off-by: Nuno Sá <nuno.sa@analog.com>
Link: https://lore.kernel.org/r/20250701-dev-adp5589-fw-v7-15-b1fcfe9e9826@analog.com
Signed-off-by: Lee Jones <lee@kernel.org>

authored by

Nuno Sá and committed by
Lee Jones
988b28a8 bd113a13

+220 -4
+1
drivers/gpio/Kconfig
··· 1263 1263 config GPIO_ADP5585 1264 1264 tristate "GPIO Support for ADP5585" 1265 1265 depends on MFD_ADP5585 1266 + select GPIOLIB_IRQCHIP 1266 1267 help 1267 1268 This option enables support for the GPIO function found in the Analog 1268 1269 Devices ADP5585.
+217 -4
drivers/gpio/gpio-adp5585.c
··· 7 7 * Copyright 2025 Analog Devices, Inc. 8 8 */ 9 9 10 + #include <linux/bitmap.h> 11 + #include <linux/bitops.h> 12 + #include <linux/container_of.h> 10 13 #include <linux/device.h> 11 14 #include <linux/gpio/driver.h> 12 15 #include <linux/mfd/adp5585.h> 13 16 #include <linux/module.h> 17 + #include <linux/mutex.h> 18 + #include <linux/notifier.h> 14 19 #include <linux/platform_device.h> 15 20 #include <linux/regmap.h> 16 21 #include <linux/types.h> ··· 41 36 struct adp5585_gpio_chip { 42 37 int (*bank)(unsigned int off); 43 38 int (*bit)(unsigned int off); 44 - unsigned int max_gpio; 45 39 unsigned int debounce_dis_a; 46 40 unsigned int rpull_cfg_a; 47 41 unsigned int gpo_data_a; 48 42 unsigned int gpo_out_a; 49 43 unsigned int gpio_dir_a; 50 44 unsigned int gpi_stat_a; 45 + unsigned int gpi_int_lvl_a; 46 + unsigned int gpi_ev_a; 47 + unsigned int gpi_ev_min; 48 + unsigned int gpi_ev_max; 51 49 bool has_bias_hole; 52 50 }; 53 51 54 52 struct adp5585_gpio_dev { 55 53 struct gpio_chip gpio_chip; 54 + struct notifier_block nb; 56 55 const struct adp5585_gpio_chip *info; 57 56 struct regmap *regmap; 57 + unsigned long irq_mask; 58 + unsigned long irq_en; 59 + unsigned long irq_active_high; 60 + /* used for irqchip bus locking */ 61 + struct mutex bus_lock; 58 62 }; 59 63 60 64 static int adp5585_gpio_bank(unsigned int off) ··· 238 224 }; 239 225 } 240 226 227 + static int adp5585_gpio_request(struct gpio_chip *chip, unsigned int off) 228 + { 229 + struct adp5585_gpio_dev *adp5585_gpio = gpiochip_get_data(chip); 230 + const struct adp5585_gpio_chip *info = adp5585_gpio->info; 231 + struct device *dev = chip->parent; 232 + struct adp5585_dev *adp5585 = dev_get_drvdata(dev->parent); 233 + const struct adp5585_regs *regs = adp5585->regs; 234 + int ret; 235 + 236 + ret = test_and_set_bit(off, adp5585->pin_usage); 237 + if (ret) 238 + return -EBUSY; 239 + 240 + /* make sure it's configured for GPIO */ 241 + return regmap_clear_bits(adp5585_gpio->regmap, 242 + regs->pin_cfg_a + info->bank(off), 243 + info->bit(off)); 244 + } 245 + 246 + static void adp5585_gpio_free(struct gpio_chip *chip, unsigned int off) 247 + { 248 + struct device *dev = chip->parent; 249 + struct adp5585_dev *adp5585 = dev_get_drvdata(dev->parent); 250 + 251 + clear_bit(off, adp5585->pin_usage); 252 + } 253 + 254 + static int adp5585_gpio_key_event(struct notifier_block *nb, unsigned long key, 255 + void *data) 256 + { 257 + struct adp5585_gpio_dev *adp5585_gpio = container_of(nb, struct adp5585_gpio_dev, nb); 258 + struct device *dev = adp5585_gpio->gpio_chip.parent; 259 + unsigned long key_press = (unsigned long)data; 260 + unsigned int irq, irq_type; 261 + struct irq_data *irqd; 262 + bool active_high; 263 + unsigned int off; 264 + 265 + /* make sure the event is for me */ 266 + if (key < adp5585_gpio->info->gpi_ev_min || key > adp5585_gpio->info->gpi_ev_max) 267 + return NOTIFY_DONE; 268 + 269 + off = key - adp5585_gpio->info->gpi_ev_min; 270 + active_high = test_bit(off, &adp5585_gpio->irq_active_high); 271 + 272 + irq = irq_find_mapping(adp5585_gpio->gpio_chip.irq.domain, off); 273 + if (!irq) 274 + return NOTIFY_BAD; 275 + 276 + irqd = irq_get_irq_data(irq); 277 + if (!irqd) { 278 + dev_err(dev, "Could not get irq(%u) data\n", irq); 279 + return NOTIFY_BAD; 280 + } 281 + 282 + dev_dbg_ratelimited(dev, "gpio-keys event(%u) press=%lu, a_high=%u\n", 283 + off, key_press, active_high); 284 + 285 + if (!active_high) 286 + key_press = !key_press; 287 + 288 + irq_type = irqd_get_trigger_type(irqd); 289 + 290 + if ((irq_type & IRQ_TYPE_EDGE_RISING && key_press) || 291 + (irq_type & IRQ_TYPE_EDGE_FALLING && !key_press)) 292 + handle_nested_irq(irq); 293 + 294 + return NOTIFY_STOP; 295 + } 296 + 297 + static void adp5585_irq_bus_lock(struct irq_data *d) 298 + { 299 + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 300 + struct adp5585_gpio_dev *adp5585_gpio = gpiochip_get_data(gc); 301 + 302 + mutex_lock(&adp5585_gpio->bus_lock); 303 + } 304 + 305 + static void adp5585_irq_bus_sync_unlock(struct irq_data *d) 306 + { 307 + struct gpio_chip *chip = irq_data_get_irq_chip_data(d); 308 + struct adp5585_gpio_dev *adp5585_gpio = gpiochip_get_data(chip); 309 + const struct adp5585_gpio_chip *info = adp5585_gpio->info; 310 + irq_hw_number_t hwirq = irqd_to_hwirq(d); 311 + bool active_high = test_bit(hwirq, &adp5585_gpio->irq_active_high); 312 + bool enabled = test_bit(hwirq, &adp5585_gpio->irq_en); 313 + bool masked = test_bit(hwirq, &adp5585_gpio->irq_mask); 314 + unsigned int bank = adp5585_gpio->info->bank(hwirq); 315 + unsigned int bit = adp5585_gpio->info->bit(hwirq); 316 + 317 + if (masked && !enabled) 318 + goto out_unlock; 319 + if (!masked && enabled) 320 + goto out_unlock; 321 + 322 + regmap_update_bits(adp5585_gpio->regmap, info->gpi_int_lvl_a + bank, bit, 323 + active_high ? bit : 0); 324 + regmap_update_bits(adp5585_gpio->regmap, info->gpi_ev_a + bank, bit, 325 + masked ? 0 : bit); 326 + assign_bit(hwirq, &adp5585_gpio->irq_en, !masked); 327 + 328 + out_unlock: 329 + mutex_unlock(&adp5585_gpio->bus_lock); 330 + } 331 + 332 + static void adp5585_irq_mask(struct irq_data *d) 333 + { 334 + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 335 + struct adp5585_gpio_dev *adp5585_gpio = gpiochip_get_data(gc); 336 + irq_hw_number_t hwirq = irqd_to_hwirq(d); 337 + 338 + __set_bit(hwirq, &adp5585_gpio->irq_mask); 339 + gpiochip_disable_irq(gc, hwirq); 340 + } 341 + 342 + static void adp5585_irq_unmask(struct irq_data *d) 343 + { 344 + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 345 + struct adp5585_gpio_dev *adp5585_gpio = gpiochip_get_data(gc); 346 + irq_hw_number_t hwirq = irqd_to_hwirq(d); 347 + 348 + gpiochip_enable_irq(gc, hwirq); 349 + __clear_bit(hwirq, &adp5585_gpio->irq_mask); 350 + } 351 + 352 + static int adp5585_irq_set_type(struct irq_data *d, unsigned int type) 353 + { 354 + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); 355 + struct adp5585_gpio_dev *adp5585_gpio = gpiochip_get_data(gc); 356 + irq_hw_number_t hwirq = irqd_to_hwirq(d); 357 + 358 + if (!(type & IRQ_TYPE_EDGE_BOTH)) 359 + return -EINVAL; 360 + 361 + assign_bit(hwirq, &adp5585_gpio->irq_active_high, 362 + type == IRQ_TYPE_EDGE_RISING); 363 + 364 + irq_set_handler_locked(d, handle_edge_irq); 365 + return 0; 366 + } 367 + 368 + static const struct irq_chip adp5585_irq_chip = { 369 + .name = "adp5585", 370 + .irq_mask = adp5585_irq_mask, 371 + .irq_unmask = adp5585_irq_unmask, 372 + .irq_bus_lock = adp5585_irq_bus_lock, 373 + .irq_bus_sync_unlock = adp5585_irq_bus_sync_unlock, 374 + .irq_set_type = adp5585_irq_set_type, 375 + .flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_IMMUTABLE, 376 + GPIOCHIP_IRQ_RESOURCE_HELPERS, 377 + }; 378 + 379 + static void adp5585_gpio_unreg_notifier(void *data) 380 + { 381 + struct adp5585_gpio_dev *adp5585_gpio = data; 382 + struct device *dev = adp5585_gpio->gpio_chip.parent; 383 + struct adp5585_dev *adp5585 = dev_get_drvdata(dev->parent); 384 + 385 + blocking_notifier_chain_unregister(&adp5585->event_notifier, 386 + &adp5585_gpio->nb); 387 + } 388 + 241 389 static int adp5585_gpio_probe(struct platform_device *pdev) 242 390 { 243 391 struct adp5585_dev *adp5585 = dev_get_drvdata(pdev->dev.parent); 244 392 const struct platform_device_id *id = platform_get_device_id(pdev); 245 393 struct adp5585_gpio_dev *adp5585_gpio; 246 394 struct device *dev = &pdev->dev; 395 + struct gpio_irq_chip *girq; 247 396 struct gpio_chip *gc; 248 397 int ret; 249 398 ··· 430 253 gc->get = adp5585_gpio_get_value; 431 254 gc->set_rv = adp5585_gpio_set_value; 432 255 gc->set_config = adp5585_gpio_set_config; 256 + gc->request = adp5585_gpio_request; 257 + gc->free = adp5585_gpio_free; 433 258 gc->can_sleep = true; 434 259 435 260 gc->base = -1; 436 - gc->ngpio = adp5585_gpio->info->max_gpio; 261 + gc->ngpio = adp5585->n_pins; 437 262 gc->label = pdev->name; 438 263 gc->owner = THIS_MODULE; 439 264 265 + if (device_property_present(dev->parent, "interrupt-controller")) { 266 + if (!adp5585->irq) 267 + return dev_err_probe(dev, -EINVAL, 268 + "Unable to serve as interrupt controller without IRQ\n"); 269 + 270 + girq = &adp5585_gpio->gpio_chip.irq; 271 + gpio_irq_chip_set_chip(girq, &adp5585_irq_chip); 272 + girq->handler = handle_bad_irq; 273 + girq->threaded = true; 274 + 275 + adp5585_gpio->nb.notifier_call = adp5585_gpio_key_event; 276 + ret = blocking_notifier_chain_register(&adp5585->event_notifier, 277 + &adp5585_gpio->nb); 278 + if (ret) 279 + return ret; 280 + 281 + ret = devm_add_action_or_reset(dev, adp5585_gpio_unreg_notifier, 282 + adp5585_gpio); 283 + if (ret) 284 + return ret; 285 + } 286 + 287 + /* everything masked by default */ 288 + adp5585_gpio->irq_mask = ~0UL; 289 + 290 + ret = devm_mutex_init(dev, &adp5585_gpio->bus_lock); 291 + if (ret) 292 + return ret; 440 293 ret = devm_gpiochip_add_data(dev, &adp5585_gpio->gpio_chip, 441 294 adp5585_gpio); 442 295 if (ret) ··· 484 277 .gpo_out_a = ADP5585_GPO_OUT_MODE_A, 485 278 .gpio_dir_a = ADP5585_GPIO_DIRECTION_A, 486 279 .gpi_stat_a = ADP5585_GPI_STATUS_A, 487 - .max_gpio = ADP5585_PIN_MAX, 488 280 .has_bias_hole = true, 281 + .gpi_ev_min = ADP5585_GPI_EVENT_START, 282 + .gpi_ev_max = ADP5585_GPI_EVENT_END, 283 + .gpi_int_lvl_a = ADP5585_GPI_INT_LEVEL_A, 284 + .gpi_ev_a = ADP5585_GPI_EVENT_EN_A, 489 285 }; 490 286 491 287 static const struct adp5585_gpio_chip adp5589_gpio_chip_info = { ··· 500 290 .gpo_out_a = ADP5589_GPO_OUT_MODE_A, 501 291 .gpio_dir_a = ADP5589_GPIO_DIRECTION_A, 502 292 .gpi_stat_a = ADP5589_GPI_STATUS_A, 503 - .max_gpio = ADP5589_PIN_MAX, 293 + .gpi_ev_min = ADP5589_GPI_EVENT_START, 294 + .gpi_ev_max = ADP5589_GPI_EVENT_END, 295 + .gpi_int_lvl_a = ADP5589_GPI_INT_LEVEL_A, 296 + .gpi_ev_a = ADP5589_GPI_EVENT_EN_A, 504 297 }; 505 298 506 299 static const struct platform_device_id adp5585_gpio_id_table[] = {
+2
include/linux/mfd/adp5585.h
··· 136 136 #define ADP5589_GPI_STATUS_A 0x16 137 137 #define ADP5589_GPI_STATUS_C 0x18 138 138 #define ADP5589_RPULL_CONFIG_A 0x19 139 + #define ADP5589_GPI_INT_LEVEL_A 0x1e 140 + #define ADP5589_GPI_EVENT_EN_A 0x21 139 141 #define ADP5589_DEBOUNCE_DIS_A 0x27 140 142 #define ADP5589_GPO_DATA_OUT_A 0x2a 141 143 #define ADP5589_GPO_OUT_MODE_A 0x2d