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.

mfd: adp5585: Add support for input devices

The ADP558x family supports a built in keypad matrix decoder which can
be added as an Input device. In order to both support the Input and the
GPIO device, we need to create a bitmap of the supported pins and track
their usage since they can either be used as GPIOs (GPIs) or as part of
the keymap.

We also need to mark special pins busy in case some features are being
used (ex: pwm or reset events).

Signed-off-by: Nuno Sá <nuno.sa@analog.com>
Link: https://lore.kernel.org/r/20250701-dev-adp5589-fw-v7-14-b1fcfe9e9826@analog.com
Signed-off-by: Lee Jones <lee@kernel.org>

authored by

Nuno Sá and committed by
Lee Jones
bd113a13 333812da

+41
+31
drivers/mfd/adp5585.c
··· 22 22 enum { 23 23 ADP5585_DEV_GPIO, 24 24 ADP5585_DEV_PWM, 25 + ADP5585_DEV_INPUT, 25 26 ADP5585_DEV_MAX 26 27 }; 27 28 28 29 static const struct mfd_cell adp5585_devs[ADP5585_DEV_MAX] = { 29 30 MFD_CELL_NAME("adp5585-gpio"), 30 31 MFD_CELL_NAME("adp5585-pwm"), 32 + MFD_CELL_NAME("adp5585-keys"), 31 33 }; 32 34 33 35 static const struct mfd_cell adp5589_devs[] = { 34 36 MFD_CELL_NAME("adp5589-gpio"), 35 37 MFD_CELL_NAME("adp5589-pwm"), 38 + MFD_CELL_NAME("adp5589-keys"), 36 39 }; 37 40 38 41 static const struct regmap_range adp5585_volatile_ranges[] = { ··· 175 172 .reset_cfg = ADP5585_RESET_CFG, 176 173 .reset1_event_a = ADP5585_RESET1_EVENT_A, 177 174 .reset2_event_a = ADP5585_RESET2_EVENT_A, 175 + .pin_cfg_a = ADP5585_PIN_CONFIG_A, 178 176 }; 179 177 180 178 static const struct adp5585_regs adp5589_regs = { ··· 186 182 .reset_cfg = ADP5589_RESET_CFG, 187 183 .reset1_event_a = ADP5589_RESET1_EVENT_A, 188 184 .reset2_event_a = ADP5589_RESET2_EVENT_A, 185 + .pin_cfg_a = ADP5589_PIN_CONFIG_A, 189 186 }; 190 187 191 188 static int adp5585_validate_event(const struct adp5585_dev *adp5585, unsigned int ev) ··· 244 239 case ADP5585_04: 245 240 adp5585->id = ADP5585_MAN_ID_VALUE; 246 241 adp5585->regs = &adp5585_regs; 242 + adp5585->n_pins = ADP5585_PIN_MAX; 243 + adp5585->reset2_out = ADP5585_RESET2_OUT; 247 244 if (adp5585->variant == ADP5585_01) 248 245 adp5585->has_pin6 = true; 249 246 regmap_config = devm_kmemdup(adp5585->dev, &adp5585_regmap_config_template, ··· 258 251 adp5585->regs = &adp5589_regs; 259 252 adp5585->has_unlock = true; 260 253 adp5585->has_pin6 = true; 254 + adp5585->n_pins = ADP5589_PIN_MAX; 255 + adp5585->reset2_out = ADP5589_RESET2_OUT; 261 256 regmap_config = devm_kmemdup(adp5585->dev, &adp5589_regmap_config_template, 262 257 sizeof(*regmap_config), GFP_KERNEL); 263 258 break; ··· 448 439 cells = adp5589_devs; 449 440 450 441 if (device_property_present(dev, "#pwm-cells")) { 442 + /* Make sure the PWM output pin is not used by the GPIO or INPUT devices */ 443 + __set_bit(ADP5585_PWM_OUT, adp5585->pin_usage); 451 444 ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, 452 445 &cells[ADP5585_DEV_PWM], 1, NULL, 0, NULL); 453 446 if (ret) ··· 461 450 &cells[ADP5585_DEV_GPIO], 1, NULL, 0, NULL); 462 451 if (ret) 463 452 return dev_err_probe(dev, ret, "Failed to add GPIO device\n"); 453 + } 454 + 455 + if (device_property_present(adp5585->dev, "adi,keypad-pins")) { 456 + ret = devm_mfd_add_devices(adp5585->dev, PLATFORM_DEVID_AUTO, 457 + &cells[ADP5585_DEV_INPUT], 1, NULL, 0, NULL); 458 + if (ret) 459 + return dev_err_probe(dev, ret, "Failed to add input device\n"); 464 460 } 465 461 466 462 return 0; ··· 536 518 unsigned int reg_val = 0, i; 537 519 int ret; 538 520 521 + /* If pin_6 (ROW5/GPI6) is not available, make sure to mark it as "busy" */ 522 + if (!adp5585->has_pin6) 523 + __set_bit(ADP5585_ROW5, adp5585->pin_usage); 524 + 539 525 /* Configure the device with reset and unlock events */ 540 526 for (i = 0; i < adp5585->nkeys_unlock; i++) { 541 527 ret = regmap_write(adp5585->regmap, ADP5589_UNLOCK1 + i, ··· 564 542 adp5585->reset1_keys[i] | ADP5585_RESET_EV_PRESS); 565 543 if (ret) 566 544 return ret; 545 + 546 + /* Mark that pin as not usable for the INPUT and GPIO devices. */ 547 + __set_bit(ADP5585_RESET1_OUT, adp5585->pin_usage); 567 548 } 568 549 569 550 for (i = 0; i < adp5585->nkeys_reset2; i++) { ··· 574 549 adp5585->reset2_keys[i] | ADP5585_RESET_EV_PRESS); 575 550 if (ret) 576 551 return ret; 552 + 553 + __set_bit(adp5585->reset2_out, adp5585->pin_usage); 577 554 } 578 555 579 556 if (adp5585->nkeys_reset1 || adp5585->nkeys_reset2) { ··· 723 696 if (id != adp5585->id) 724 697 return dev_err_probe(&i2c->dev, -ENODEV, 725 698 "Invalid device ID 0x%02x\n", id); 699 + 700 + adp5585->pin_usage = devm_bitmap_zalloc(&i2c->dev, adp5585->n_pins, GFP_KERNEL); 701 + if (!adp5585->pin_usage) 702 + return -ENOMEM; 726 703 727 704 ret = adp5585_parse_fw(adp5585); 728 705 if (ret)
+10
include/linux/mfd/adp5585.h
··· 126 126 #define ADP5585_GPI_EVENT_END 47 127 127 #define ADP5585_ROW5_KEY_EVENT_START 1 128 128 #define ADP5585_ROW5_KEY_EVENT_END 30 129 + #define ADP5585_PWM_OUT 3 130 + #define ADP5585_RESET1_OUT 4 131 + #define ADP5585_RESET2_OUT 9 132 + #define ADP5585_ROW5 5 129 133 130 134 /* ADP5589 */ 131 135 #define ADP5589_MAN_ID_VALUE 0x10 ··· 158 154 #define ADP5589_PWM_ONT_LOW 0x40 159 155 #define ADP5589_PWM_CFG 0x42 160 156 #define ADP5589_POLL_PTIME_CFG 0x48 157 + #define ADP5589_PIN_CONFIG_A 0x49 161 158 #define ADP5589_PIN_CONFIG_D 0x4C 162 159 #define ADP5589_GENERAL_CFG 0x4d 163 160 #define ADP5589_INT_EN 0x4e ··· 170 165 #define ADP5589_GPI_EVENT_START 97 171 166 #define ADP5589_GPI_EVENT_END 115 172 167 #define ADP5589_UNLOCK_WILDCARD 127 168 + #define ADP5589_RESET2_OUT 12 173 169 174 170 struct regmap; 175 171 ··· 194 188 unsigned int reset_cfg; 195 189 unsigned int reset1_event_a; 196 190 unsigned int reset2_event_a; 191 + unsigned int pin_cfg_a; 197 192 }; 198 193 199 194 struct adp5585_dev { ··· 202 195 struct regmap *regmap; 203 196 const struct adp5585_regs *regs; 204 197 struct blocking_notifier_head event_notifier; 198 + unsigned long *pin_usage; 199 + unsigned int n_pins; 200 + unsigned int reset2_out; 205 201 enum adp5585_variant variant; 206 202 unsigned int id; 207 203 bool has_unlock;