/* * Chip variants differ in the default configuration of pull-up and pull-down * resistors, and therefore have different default register values: * * - The -00, -01 and -03 variants (collectively referred to as * ADP5585_REGMAP_00) have pull-up on all GPIO pins by default. * - The -02 variant has no default pull-up or pull-down resistors. * - The -04 variant has default pull-down resistors on all GPIO pins.
*/
staticint adp5585_validate_event(conststruct adp5585_dev *adp5585, unsignedint ev)
{ if (adp5585->has_pin6) { if (ev >= ADP5585_ROW5_KEY_EVENT_START && ev <= ADP5585_ROW5_KEY_EVENT_END) return 0; if (ev >= ADP5585_GPI_EVENT_START && ev <= ADP5585_GPI_EVENT_END) return 0;
return dev_err_probe(adp5585->dev, -EINVAL, "Invalid unlock/reset event(%u) for this device\n", ev);
}
if (ev >= ADP5585_KEY_EVENT_START && ev <= ADP5585_KEY_EVENT_END) return 0; if (ev >= ADP5585_GPI_EVENT_START && ev <= ADP5585_GPI_EVENT_END) { /* * Some variants of the adp5585 do not have the Row 5 * (meaning pin 6 or GPIO 6) available. Instead that pin serves * as a reset pin. So, we need to make sure no event is * configured for it.
*/ if (ev == (ADP5585_GPI_EVENT_START + 5)) return dev_err_probe(adp5585->dev, -EINVAL, "Invalid unlock/reset event(%u). R5 not available\n",
ev); return 0;
}
return dev_err_probe(adp5585->dev, -EINVAL, "Invalid unlock/reset event(%u) for this device\n", ev);
}
staticint adp5589_validate_event(conststruct adp5585_dev *adp5585, unsignedint ev)
{ if (ev >= ADP5589_KEY_EVENT_START && ev <= ADP5589_KEY_EVENT_END) return 0; if (ev >= ADP5589_GPI_EVENT_START && ev <= ADP5589_GPI_EVENT_END) return 0;
return dev_err_probe(adp5585->dev, -EINVAL, "Invalid unlock/reset event(%u) for this device\n", ev);
}
/* * The device has the capability of handling special events through GPIs or a Keypad: * unlock events: Unlock the keymap until one of the configured events is detected. * reset events: Generate a reset pulse when one of the configured events is detected.
*/
ret = device_property_count_u32(dev, prop); if (ret < 0) return 0;
*n_events = ret;
if (!adp5585->has_unlock && !reset_ev) return dev_err_probe(dev, -EOPNOTSUPP, "Unlock keys not supported\n");
if (*n_events > max_evs) return dev_err_probe(dev, -EINVAL, "Invalid number of keys(%u > %u) for %s\n",
*n_events, max_evs, prop);
ret = device_property_read_u32_array(dev, prop, events, *n_events); if (ret) return ret;
for (ev = 0; ev < *n_events; ev++) { if (!reset_ev && events[ev] == ADP5589_UNLOCK_WILDCARD) continue;
if (adp5585->id == ADP5585_MAN_ID_VALUE)
ret = adp5585_validate_event(adp5585, events[ev]); else
ret = adp5589_validate_event(adp5585, events[ev]); if (ret) return ret;
}
if (device_property_present(dev, "#pwm-cells")) { /* Make sure the PWM output pin is not used by the GPIO or INPUT devices */
__set_bit(ADP5585_PWM_OUT, adp5585->pin_usage);
ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO,
&cells[ADP5585_DEV_PWM], 1, NULL, 0, NULL); if (ret) return dev_err_probe(dev, ret, "Failed to add PWM device\n");
}
if (device_property_present(dev, "#gpio-cells")) {
ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO,
&cells[ADP5585_DEV_GPIO], 1, NULL, 0, NULL); if (ret) return dev_err_probe(dev, ret, "Failed to add GPIO device\n");
}
if (device_property_present(adp5585->dev, "adi,keypad-pins")) {
ret = devm_mfd_add_devices(adp5585->dev, PLATFORM_DEVID_AUTO,
&cells[ADP5585_DEV_INPUT], 1, NULL, 0, NULL); if (ret) return dev_err_probe(dev, ret, "Failed to add input device\n");
}
/* If pin_6 (ROW5/GPI6) is not available, make sure to mark it as "busy" */ if (!adp5585->has_pin6)
__set_bit(ADP5585_ROW5, adp5585->pin_usage);
/* Configure the device with reset and unlock events */ for (i = 0; i < adp5585->nkeys_unlock; i++) {
ret = regmap_write(adp5585->regmap, ADP5589_UNLOCK1 + i,
adp5585->unlock_keys[i] | ADP5589_UNLOCK_EV_PRESS); if (ret) return ret;
}
if (adp5585->nkeys_unlock) {
ret = regmap_update_bits(adp5585->regmap, ADP5589_UNLOCK_TIMERS,
ADP5589_UNLOCK_TIMER, adp5585->unlock_time); if (ret) return ret;
ret = regmap_set_bits(adp5585->regmap, ADP5589_LOCK_CFG, ADP5589_LOCK_EN); if (ret) return ret;
}
for (i = 0; i < adp5585->nkeys_reset1; i++) {
ret = regmap_write(adp5585->regmap, regs->reset1_event_a + i,
adp5585->reset1_keys[i] | ADP5585_RESET_EV_PRESS); if (ret) return ret;
/* Mark that pin as not usable for the INPUT and GPIO devices. */
__set_bit(ADP5585_RESET1_OUT, adp5585->pin_usage);
}
for (i = 0; i < adp5585->nkeys_reset2; i++) {
ret = regmap_write(adp5585->regmap, regs->reset2_event_a + i,
adp5585->reset2_keys[i] | ADP5585_RESET_EV_PRESS); if (ret) return ret;
if (adp5585->nkeys_reset1 || adp5585->nkeys_reset2) {
ret = regmap_write(adp5585->regmap, regs->reset_cfg, adp5585->reset_cfg); if (ret) return ret;
/* If there's a reset1 event, then R4 is used as an output for the reset signal */ if (adp5585->nkeys_reset1)
reg_val = ADP5585_R4_EXTEND_CFG_RESET1; /* If there's a reset2 event, then C4 is used as an output for the reset signal */ if (adp5585->nkeys_reset2)
reg_val |= ADP5585_C4_EXTEND_CFG_RESET2;
ret = regmap_update_bits(adp5585->regmap, regs->ext_cfg,
ADP5585_C4_EXTEND_CFG_MASK | ADP5585_R4_EXTEND_CFG_MASK,
reg_val); if (ret) return ret;
}
/* Clear any possible event by reading all the FIFO entries */ for (i = 0; i < ADP5585_EV_MAX; i++) {
ret = regmap_read(adp5585->regmap, ADP5585_FIFO_1 + i, ®_val); if (ret) return ret;
}
ret = regmap_write(adp5585->regmap, regs->poll_ptime_cfg, adp5585->ev_poll_time); if (ret) return ret;
/* * Enable the internal oscillator, as it's shared between multiple * functions.
*/
ret = regmap_write(adp5585->regmap, regs->gen_cfg,
ADP5585_OSC_FREQ_500KHZ | ADP5585_INT_CFG | ADP5585_OSC_EN); if (ret) return ret;
staticint adp5585_parse_fw(struct adp5585_dev *adp5585)
{ unsignedint prop_val; int ret;
ret = device_property_read_u32(adp5585->dev, "poll-interval", &prop_val); if (!ret) {
adp5585->ev_poll_time = prop_val / 10 - 1; /* * ev_poll_time is the raw value to be written on the register and 0 to 3 are the * valid values.
*/ if (adp5585->ev_poll_time > 3) return dev_err_probe(adp5585->dev, -EINVAL, "Invalid value(%u) for poll-interval\n", prop_val);
}
ret = adp5585_unlock_ev_parse(adp5585); if (ret) return ret;
ret = devm_request_threaded_irq(&i2c->dev, i2c->irq, NULL, adp5585_irq,
IRQF_ONESHOT, i2c->name, adp5585); if (ret) return ret;
/* * Clear any possible outstanding interrupt before enabling them. We do that by reading * the status register and writing back the same value.
*/
ret = regmap_read(adp5585->regmap, ADP5585_INT_STATUS, &stat); if (ret) return ret;
ret = regmap_write(adp5585->regmap, ADP5585_INT_STATUS, stat); if (ret) return ret;
ret = regmap_write(adp5585->regmap, regs->int_en, ADP5585_OVRFLOW_IEN | ADP5585_EVENT_IEN); if (ret) return ret;
adp5585->variant = (enum adp5585_variant)(uintptr_t)i2c_get_match_data(i2c); if (!adp5585->variant) return -ENODEV;
regmap_config = adp5585_fill_variant_config(adp5585); if (IS_ERR(regmap_config)) return PTR_ERR(regmap_config);
ret = devm_regulator_get_enable(&i2c->dev, "vdd"); if (ret) return ret;
gpio = devm_gpiod_get_optional(&i2c->dev, "reset", GPIOD_OUT_HIGH); if (IS_ERR(gpio)) return PTR_ERR(gpio);
/* * Note the timings are not documented anywhere in the datasheet. They are just * reasonable values that work.
*/ if (gpio) {
fsleep(30);
gpiod_set_value_cansleep(gpio, 0);
fsleep(60);
}
adp5585->regmap = devm_regmap_init_i2c(i2c, regmap_config); if (IS_ERR(adp5585->regmap)) return dev_err_probe(&i2c->dev, PTR_ERR(adp5585->regmap), "Failed to initialize register map\n");
ret = regmap_read(adp5585->regmap, ADP5585_ID, &id); if (ret) return dev_err_probe(&i2c->dev, ret, "Failed to read device ID\n");
id &= ADP5585_MAN_ID_MASK; if (id != adp5585->id) return dev_err_probe(&i2c->dev, -ENODEV, "Invalid device ID 0x%02x\n", id);
adp5585->pin_usage = devm_bitmap_zalloc(&i2c->dev, adp5585->n_pins, GFP_KERNEL); if (!adp5585->pin_usage) return -ENOMEM;
ret = adp5585_parse_fw(adp5585); if (ret) return ret;
ret = adp5585_setup(adp5585); if (ret) return ret;
ret = adp5585_add_devices(adp5585); if (ret) return ret;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.