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: Support reset and unlock events

The ADP558x family of devices can be programmed to respond to some
especial events, In case of the unlock events, one can lock the keypad
and use KEYS or GPIs events to unlock it. For the reset events, one can
again use a combinations of GPIs/KEYs in order to generate an event that
will trigger the device to generate an output reset pulse.

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

authored by

Nuno Sá and committed by
Lee Jones
333812da 47a1f759

+312 -2
+272 -2
drivers/mfd/adp5585.c
··· 169 169 .int_en = ADP5585_INT_EN, 170 170 .gen_cfg = ADP5585_GENERAL_CFG, 171 171 .poll_ptime_cfg = ADP5585_POLL_PTIME_CFG, 172 + .reset_cfg = ADP5585_RESET_CFG, 173 + .reset1_event_a = ADP5585_RESET1_EVENT_A, 174 + .reset2_event_a = ADP5585_RESET2_EVENT_A, 172 175 }; 173 176 174 177 static const struct adp5585_regs adp5589_regs = { ··· 179 176 .int_en = ADP5589_INT_EN, 180 177 .gen_cfg = ADP5589_GENERAL_CFG, 181 178 .poll_ptime_cfg = ADP5589_POLL_PTIME_CFG, 179 + .reset_cfg = ADP5589_RESET_CFG, 180 + .reset1_event_a = ADP5589_RESET1_EVENT_A, 181 + .reset2_event_a = ADP5589_RESET2_EVENT_A, 182 182 }; 183 + 184 + static int adp5585_validate_event(const struct adp5585_dev *adp5585, unsigned int ev) 185 + { 186 + if (adp5585->has_pin6) { 187 + if (ev >= ADP5585_ROW5_KEY_EVENT_START && ev <= ADP5585_ROW5_KEY_EVENT_END) 188 + return 0; 189 + if (ev >= ADP5585_GPI_EVENT_START && ev <= ADP5585_GPI_EVENT_END) 190 + return 0; 191 + 192 + return dev_err_probe(adp5585->dev, -EINVAL, 193 + "Invalid unlock/reset event(%u) for this device\n", ev); 194 + } 195 + 196 + if (ev >= ADP5585_KEY_EVENT_START && ev <= ADP5585_KEY_EVENT_END) 197 + return 0; 198 + if (ev >= ADP5585_GPI_EVENT_START && ev <= ADP5585_GPI_EVENT_END) { 199 + /* 200 + * Some variants of the adp5585 do not have the Row 5 201 + * (meaning pin 6 or GPIO 6) available. Instead that pin serves 202 + * as a reset pin. So, we need to make sure no event is 203 + * configured for it. 204 + */ 205 + if (ev == (ADP5585_GPI_EVENT_START + 5)) 206 + return dev_err_probe(adp5585->dev, -EINVAL, 207 + "Invalid unlock/reset event(%u). R5 not available\n", 208 + ev); 209 + return 0; 210 + } 211 + 212 + return dev_err_probe(adp5585->dev, -EINVAL, 213 + "Invalid unlock/reset event(%u) for this device\n", ev); 214 + } 215 + 216 + static int adp5589_validate_event(const struct adp5585_dev *adp5585, unsigned int ev) 217 + { 218 + if (ev >= ADP5589_KEY_EVENT_START && ev <= ADP5589_KEY_EVENT_END) 219 + return 0; 220 + if (ev >= ADP5589_GPI_EVENT_START && ev <= ADP5589_GPI_EVENT_END) 221 + return 0; 222 + 223 + return dev_err_probe(adp5585->dev, -EINVAL, 224 + "Invalid unlock/reset event(%u) for this device\n", ev); 225 + } 183 226 184 227 static struct regmap_config *adp5585_fill_variant_config(struct adp5585_dev *adp5585) 185 228 { ··· 239 190 case ADP5585_04: 240 191 adp5585->id = ADP5585_MAN_ID_VALUE; 241 192 adp5585->regs = &adp5585_regs; 193 + if (adp5585->variant == ADP5585_01) 194 + adp5585->has_pin6 = true; 242 195 regmap_config = devm_kmemdup(adp5585->dev, &adp5585_regmap_config_template, 243 196 sizeof(*regmap_config), GFP_KERNEL); 244 197 break; ··· 249 198 case ADP5589_02: 250 199 adp5585->id = ADP5589_MAN_ID_VALUE; 251 200 adp5585->regs = &adp5589_regs; 201 + adp5585->has_unlock = true; 202 + adp5585->has_pin6 = true; 252 203 regmap_config = devm_kmemdup(adp5585->dev, &adp5589_regmap_config_template, 253 204 sizeof(*regmap_config), GFP_KERNEL); 254 205 break; ··· 264 211 regmap_config->reg_defaults_raw = adp5585_regmap_defaults[adp5585->variant]; 265 212 266 213 return regmap_config; 214 + } 215 + 216 + static int adp5585_parse_ev_array(const struct adp5585_dev *adp5585, const char *prop, u32 *events, 217 + u32 *n_events, u32 max_evs, bool reset_ev) 218 + { 219 + struct device *dev = adp5585->dev; 220 + unsigned int ev; 221 + int ret; 222 + 223 + /* 224 + * The device has the capability of handling special events through GPIs or a Keypad: 225 + * unlock events: Unlock the keymap until one of the configured events is detected. 226 + * reset events: Generate a reset pulse when one of the configured events is detected. 227 + */ 228 + ret = device_property_count_u32(dev, prop); 229 + if (ret < 0) 230 + return 0; 231 + 232 + *n_events = ret; 233 + 234 + if (!adp5585->has_unlock && !reset_ev) 235 + return dev_err_probe(dev, -EOPNOTSUPP, "Unlock keys not supported\n"); 236 + 237 + if (*n_events > max_evs) 238 + return dev_err_probe(dev, -EINVAL, 239 + "Invalid number of keys(%u > %u) for %s\n", 240 + *n_events, max_evs, prop); 241 + 242 + ret = device_property_read_u32_array(dev, prop, events, *n_events); 243 + if (ret) 244 + return ret; 245 + 246 + for (ev = 0; ev < *n_events; ev++) { 247 + if (!reset_ev && events[ev] == ADP5589_UNLOCK_WILDCARD) 248 + continue; 249 + 250 + if (adp5585->id == ADP5585_MAN_ID_VALUE) 251 + ret = adp5585_validate_event(adp5585, events[ev]); 252 + else 253 + ret = adp5589_validate_event(adp5585, events[ev]); 254 + if (ret) 255 + return ret; 256 + } 257 + 258 + return 0; 259 + } 260 + 261 + static int adp5585_unlock_ev_parse(struct adp5585_dev *adp5585) 262 + { 263 + struct device *dev = adp5585->dev; 264 + int ret; 265 + 266 + ret = adp5585_parse_ev_array(adp5585, "adi,unlock-events", adp5585->unlock_keys, 267 + &adp5585->nkeys_unlock, ARRAY_SIZE(adp5585->unlock_keys), 268 + false); 269 + if (ret) 270 + return ret; 271 + if (!adp5585->nkeys_unlock) 272 + return 0; 273 + 274 + ret = device_property_read_u32(dev, "adi,unlock-trigger-sec", &adp5585->unlock_time); 275 + if (!ret) { 276 + if (adp5585->unlock_time > ADP5585_MAX_UNLOCK_TIME_SEC) 277 + return dev_err_probe(dev, -EINVAL, 278 + "Invalid unlock time(%u > %d)\n", 279 + adp5585->unlock_time, 280 + ADP5585_MAX_UNLOCK_TIME_SEC); 281 + } 282 + 283 + return 0; 284 + } 285 + 286 + static int adp5585_reset_ev_parse(struct adp5585_dev *adp5585) 287 + { 288 + struct device *dev = adp5585->dev; 289 + u32 prop_val; 290 + int ret; 291 + 292 + ret = adp5585_parse_ev_array(adp5585, "adi,reset1-events", adp5585->reset1_keys, 293 + &adp5585->nkeys_reset1, 294 + ARRAY_SIZE(adp5585->reset1_keys), true); 295 + if (ret) 296 + return ret; 297 + 298 + ret = adp5585_parse_ev_array(adp5585, "adi,reset2-events", 299 + adp5585->reset2_keys, 300 + &adp5585->nkeys_reset2, 301 + ARRAY_SIZE(adp5585->reset2_keys), true); 302 + if (ret) 303 + return ret; 304 + 305 + if (!adp5585->nkeys_reset1 && !adp5585->nkeys_reset2) 306 + return 0; 307 + 308 + if (adp5585->nkeys_reset1 && device_property_read_bool(dev, "adi,reset1-active-high")) 309 + adp5585->reset_cfg |= FIELD_PREP(ADP5585_RESET1_POL, 1); 310 + 311 + if (adp5585->nkeys_reset2 && device_property_read_bool(dev, "adi,reset2-active-high")) 312 + adp5585->reset_cfg |= FIELD_PREP(ADP5585_RESET2_POL, 1); 313 + 314 + if (device_property_read_bool(dev, "adi,rst-passthrough-enable")) 315 + adp5585->reset_cfg |= FIELD_PREP(ADP5585_RST_PASSTHRU_EN, 1); 316 + 317 + ret = device_property_read_u32(dev, "adi,reset-trigger-ms", &prop_val); 318 + if (!ret) { 319 + switch (prop_val) { 320 + case 0: 321 + adp5585->reset_cfg |= FIELD_PREP(ADP5585_RESET_TRIG_TIME, 0); 322 + break; 323 + case 1000: 324 + adp5585->reset_cfg |= FIELD_PREP(ADP5585_RESET_TRIG_TIME, 1); 325 + break; 326 + case 1500: 327 + adp5585->reset_cfg |= FIELD_PREP(ADP5585_RESET_TRIG_TIME, 2); 328 + break; 329 + case 2000: 330 + adp5585->reset_cfg |= FIELD_PREP(ADP5585_RESET_TRIG_TIME, 3); 331 + break; 332 + case 2500: 333 + adp5585->reset_cfg |= FIELD_PREP(ADP5585_RESET_TRIG_TIME, 4); 334 + break; 335 + case 3000: 336 + adp5585->reset_cfg |= FIELD_PREP(ADP5585_RESET_TRIG_TIME, 5); 337 + break; 338 + case 3500: 339 + adp5585->reset_cfg |= FIELD_PREP(ADP5585_RESET_TRIG_TIME, 6); 340 + break; 341 + case 4000: 342 + adp5585->reset_cfg |= FIELD_PREP(ADP5585_RESET_TRIG_TIME, 7); 343 + break; 344 + default: 345 + return dev_err_probe(dev, -EINVAL, 346 + "Invalid value(%u) for adi,reset-trigger-ms\n", 347 + prop_val); 348 + } 349 + } 350 + 351 + ret = device_property_read_u32(dev, "adi,reset-pulse-width-us", &prop_val); 352 + if (!ret) { 353 + switch (prop_val) { 354 + case 500: 355 + adp5585->reset_cfg |= FIELD_PREP(ADP5585_PULSE_WIDTH, 0); 356 + break; 357 + case 1000: 358 + adp5585->reset_cfg |= FIELD_PREP(ADP5585_PULSE_WIDTH, 1); 359 + break; 360 + case 2000: 361 + adp5585->reset_cfg |= FIELD_PREP(ADP5585_PULSE_WIDTH, 2); 362 + break; 363 + case 10000: 364 + adp5585->reset_cfg |= FIELD_PREP(ADP5585_PULSE_WIDTH, 3); 365 + break; 366 + default: 367 + return dev_err_probe(dev, -EINVAL, 368 + "Invalid value(%u) for adi,reset-pulse-width-us\n", 369 + prop_val); 370 + } 371 + return ret; 372 + } 373 + 374 + return 0; 267 375 } 268 376 269 377 static int adp5585_add_devices(const struct adp5585_dev *adp5585) ··· 515 301 static int adp5585_setup(struct adp5585_dev *adp5585) 516 302 { 517 303 const struct adp5585_regs *regs = adp5585->regs; 518 - unsigned int reg_val, i; 304 + unsigned int reg_val = 0, i; 519 305 int ret; 306 + 307 + /* Configure the device with reset and unlock events */ 308 + for (i = 0; i < adp5585->nkeys_unlock; i++) { 309 + ret = regmap_write(adp5585->regmap, ADP5589_UNLOCK1 + i, 310 + adp5585->unlock_keys[i] | ADP5589_UNLOCK_EV_PRESS); 311 + if (ret) 312 + return ret; 313 + } 314 + 315 + if (adp5585->nkeys_unlock) { 316 + ret = regmap_update_bits(adp5585->regmap, ADP5589_UNLOCK_TIMERS, 317 + ADP5589_UNLOCK_TIMER, adp5585->unlock_time); 318 + if (ret) 319 + return ret; 320 + 321 + ret = regmap_set_bits(adp5585->regmap, ADP5589_LOCK_CFG, ADP5589_LOCK_EN); 322 + if (ret) 323 + return ret; 324 + } 325 + 326 + for (i = 0; i < adp5585->nkeys_reset1; i++) { 327 + ret = regmap_write(adp5585->regmap, regs->reset1_event_a + i, 328 + adp5585->reset1_keys[i] | ADP5585_RESET_EV_PRESS); 329 + if (ret) 330 + return ret; 331 + } 332 + 333 + for (i = 0; i < adp5585->nkeys_reset2; i++) { 334 + ret = regmap_write(adp5585->regmap, regs->reset2_event_a + i, 335 + adp5585->reset2_keys[i] | ADP5585_RESET_EV_PRESS); 336 + if (ret) 337 + return ret; 338 + } 339 + 340 + if (adp5585->nkeys_reset1 || adp5585->nkeys_reset2) { 341 + ret = regmap_write(adp5585->regmap, regs->reset_cfg, adp5585->reset_cfg); 342 + if (ret) 343 + return ret; 344 + 345 + /* If there's a reset1 event, then R4 is used as an output for the reset signal */ 346 + if (adp5585->nkeys_reset1) 347 + reg_val = ADP5585_R4_EXTEND_CFG_RESET1; 348 + /* If there's a reset2 event, then C4 is used as an output for the reset signal */ 349 + if (adp5585->nkeys_reset2) 350 + reg_val |= ADP5585_C4_EXTEND_CFG_RESET2; 351 + 352 + ret = regmap_update_bits(adp5585->regmap, regs->ext_cfg, 353 + ADP5585_C4_EXTEND_CFG_MASK | ADP5585_R4_EXTEND_CFG_MASK, 354 + reg_val); 355 + if (ret) 356 + return ret; 357 + } 520 358 521 359 /* Clear any possible event by reading all the FIFO entries */ 522 360 for (i = 0; i < ADP5585_EV_MAX; i++) { ··· 610 344 "Invalid value(%u) for poll-interval\n", prop_val); 611 345 } 612 346 613 - return 0; 347 + ret = adp5585_unlock_ev_parse(adp5585); 348 + if (ret) 349 + return ret; 350 + 351 + return adp5585_reset_ev_parse(adp5585); 614 352 } 615 353 616 354 static void adp5585_irq_disable(void *data)
+40
include/linux/mfd/adp5585.h
··· 68 68 #define ADP5585_GPIO_DIRECTION_A 0x27 69 69 #define ADP5585_GPIO_DIRECTION_B 0x28 70 70 #define ADP5585_RESET1_EVENT_A 0x29 71 + #define ADP5585_RESET_EV_PRESS BIT(7) 71 72 #define ADP5585_RESET1_EVENT_B 0x2a 72 73 #define ADP5585_RESET1_EVENT_C 0x2b 73 74 #define ADP5585_RESET2_EVENT_A 0x2c ··· 119 118 #define ADP5585_MAX_REG ADP5585_INT_EN 120 119 121 120 #define ADP5585_PIN_MAX 11 121 + #define ADP5585_MAX_UNLOCK_TIME_SEC 7 122 + #define ADP5585_KEY_EVENT_START 1 123 + #define ADP5585_KEY_EVENT_END 25 124 + #define ADP5585_GPI_EVENT_START 37 125 + #define ADP5585_GPI_EVENT_END 47 126 + #define ADP5585_ROW5_KEY_EVENT_START 1 127 + #define ADP5585_ROW5_KEY_EVENT_END 30 122 128 123 129 /* ADP5589 */ 124 130 #define ADP5589_MAN_ID_VALUE 0x10 ··· 136 128 #define ADP5589_GPO_DATA_OUT_A 0x2a 137 129 #define ADP5589_GPO_OUT_MODE_A 0x2d 138 130 #define ADP5589_GPIO_DIRECTION_A 0x30 131 + #define ADP5589_UNLOCK1 0x33 132 + #define ADP5589_UNLOCK_EV_PRESS BIT(7) 133 + #define ADP5589_UNLOCK_TIMERS 0x36 134 + #define ADP5589_UNLOCK_TIMER GENMASK(2, 0) 135 + #define ADP5589_LOCK_CFG 0x37 136 + #define ADP5589_LOCK_EN BIT(0) 137 + #define ADP5589_RESET1_EVENT_A 0x38 138 + #define ADP5589_RESET2_EVENT_A 0x3B 139 + #define ADP5589_RESET_CFG 0x3D 140 + #define ADP5585_RESET2_POL BIT(7) 141 + #define ADP5585_RESET1_POL BIT(6) 142 + #define ADP5585_RST_PASSTHRU_EN BIT(5) 143 + #define ADP5585_RESET_TRIG_TIME GENMASK(4, 2) 144 + #define ADP5585_PULSE_WIDTH GENMASK(1, 0) 139 145 #define ADP5589_PWM_OFFT_LOW 0x3e 140 146 #define ADP5589_PWM_ONT_LOW 0x40 141 147 #define ADP5589_PWM_CFG 0x42 ··· 160 138 #define ADP5589_MAX_REG ADP5589_INT_EN 161 139 162 140 #define ADP5589_PIN_MAX 19 141 + #define ADP5589_KEY_EVENT_START 1 142 + #define ADP5589_KEY_EVENT_END 88 143 + #define ADP5589_GPI_EVENT_START 97 144 + #define ADP5589_GPI_EVENT_END 115 145 + #define ADP5589_UNLOCK_WILDCARD 127 163 146 164 147 struct regmap; 165 148 ··· 185 158 unsigned int ext_cfg; 186 159 unsigned int int_en; 187 160 unsigned int poll_ptime_cfg; 161 + unsigned int reset_cfg; 162 + unsigned int reset1_event_a; 163 + unsigned int reset2_event_a; 188 164 }; 189 165 190 166 struct adp5585_dev { ··· 197 167 struct blocking_notifier_head event_notifier; 198 168 enum adp5585_variant variant; 199 169 unsigned int id; 170 + bool has_unlock; 171 + bool has_pin6; 200 172 int irq; 201 173 unsigned int ev_poll_time; 174 + unsigned int unlock_time; 175 + unsigned int unlock_keys[2]; 176 + unsigned int nkeys_unlock; 177 + unsigned int reset1_keys[3]; 178 + unsigned int nkeys_reset1; 179 + unsigned int reset2_keys[2]; 180 + unsigned int nkeys_reset2; 181 + u8 reset_cfg; 202 182 }; 203 183 204 184 #endif