Skip to content

Commit 333812d

Browse files
nunojsalag-linaro
authored andcommitted
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>
1 parent 47a1f75 commit 333812d

2 files changed

Lines changed: 312 additions & 2 deletions

File tree

drivers/mfd/adp5585.c

Lines changed: 272 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,15 +169,64 @@ static const struct adp5585_regs adp5585_regs = {
169169
.int_en = ADP5585_INT_EN,
170170
.gen_cfg = ADP5585_GENERAL_CFG,
171171
.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,
172175
};
173176

174177
static const struct adp5585_regs adp5589_regs = {
175178
.ext_cfg = ADP5589_PIN_CONFIG_D,
176179
.int_en = ADP5589_INT_EN,
177180
.gen_cfg = ADP5589_GENERAL_CFG,
178181
.poll_ptime_cfg = ADP5589_POLL_PTIME_CFG,
182+
.reset_cfg = ADP5589_RESET_CFG,
183+
.reset1_event_a = ADP5589_RESET1_EVENT_A,
184+
.reset2_event_a = ADP5589_RESET2_EVENT_A,
179185
};
180186

187+
static int adp5585_validate_event(const struct adp5585_dev *adp5585, unsigned int ev)
188+
{
189+
if (adp5585->has_pin6) {
190+
if (ev >= ADP5585_ROW5_KEY_EVENT_START && ev <= ADP5585_ROW5_KEY_EVENT_END)
191+
return 0;
192+
if (ev >= ADP5585_GPI_EVENT_START && ev <= ADP5585_GPI_EVENT_END)
193+
return 0;
194+
195+
return dev_err_probe(adp5585->dev, -EINVAL,
196+
"Invalid unlock/reset event(%u) for this device\n", ev);
197+
}
198+
199+
if (ev >= ADP5585_KEY_EVENT_START && ev <= ADP5585_KEY_EVENT_END)
200+
return 0;
201+
if (ev >= ADP5585_GPI_EVENT_START && ev <= ADP5585_GPI_EVENT_END) {
202+
/*
203+
* Some variants of the adp5585 do not have the Row 5
204+
* (meaning pin 6 or GPIO 6) available. Instead that pin serves
205+
* as a reset pin. So, we need to make sure no event is
206+
* configured for it.
207+
*/
208+
if (ev == (ADP5585_GPI_EVENT_START + 5))
209+
return dev_err_probe(adp5585->dev, -EINVAL,
210+
"Invalid unlock/reset event(%u). R5 not available\n",
211+
ev);
212+
return 0;
213+
}
214+
215+
return dev_err_probe(adp5585->dev, -EINVAL,
216+
"Invalid unlock/reset event(%u) for this device\n", ev);
217+
}
218+
219+
static int adp5589_validate_event(const struct adp5585_dev *adp5585, unsigned int ev)
220+
{
221+
if (ev >= ADP5589_KEY_EVENT_START && ev <= ADP5589_KEY_EVENT_END)
222+
return 0;
223+
if (ev >= ADP5589_GPI_EVENT_START && ev <= ADP5589_GPI_EVENT_END)
224+
return 0;
225+
226+
return dev_err_probe(adp5585->dev, -EINVAL,
227+
"Invalid unlock/reset event(%u) for this device\n", ev);
228+
}
229+
181230
static struct regmap_config *adp5585_fill_variant_config(struct adp5585_dev *adp5585)
182231
{
183232
struct regmap_config *regmap_config;
@@ -190,6 +239,8 @@ static struct regmap_config *adp5585_fill_variant_config(struct adp5585_dev *adp
190239
case ADP5585_04:
191240
adp5585->id = ADP5585_MAN_ID_VALUE;
192241
adp5585->regs = &adp5585_regs;
242+
if (adp5585->variant == ADP5585_01)
243+
adp5585->has_pin6 = true;
193244
regmap_config = devm_kmemdup(adp5585->dev, &adp5585_regmap_config_template,
194245
sizeof(*regmap_config), GFP_KERNEL);
195246
break;
@@ -198,6 +249,8 @@ static struct regmap_config *adp5585_fill_variant_config(struct adp5585_dev *adp
198249
case ADP5589_02:
199250
adp5585->id = ADP5589_MAN_ID_VALUE;
200251
adp5585->regs = &adp5589_regs;
252+
adp5585->has_unlock = true;
253+
adp5585->has_pin6 = true;
201254
regmap_config = devm_kmemdup(adp5585->dev, &adp5589_regmap_config_template,
202255
sizeof(*regmap_config), GFP_KERNEL);
203256
break;
@@ -213,6 +266,167 @@ static struct regmap_config *adp5585_fill_variant_config(struct adp5585_dev *adp
213266
return regmap_config;
214267
}
215268

269+
static int adp5585_parse_ev_array(const struct adp5585_dev *adp5585, const char *prop, u32 *events,
270+
u32 *n_events, u32 max_evs, bool reset_ev)
271+
{
272+
struct device *dev = adp5585->dev;
273+
unsigned int ev;
274+
int ret;
275+
276+
/*
277+
* The device has the capability of handling special events through GPIs or a Keypad:
278+
* unlock events: Unlock the keymap until one of the configured events is detected.
279+
* reset events: Generate a reset pulse when one of the configured events is detected.
280+
*/
281+
ret = device_property_count_u32(dev, prop);
282+
if (ret < 0)
283+
return 0;
284+
285+
*n_events = ret;
286+
287+
if (!adp5585->has_unlock && !reset_ev)
288+
return dev_err_probe(dev, -EOPNOTSUPP, "Unlock keys not supported\n");
289+
290+
if (*n_events > max_evs)
291+
return dev_err_probe(dev, -EINVAL,
292+
"Invalid number of keys(%u > %u) for %s\n",
293+
*n_events, max_evs, prop);
294+
295+
ret = device_property_read_u32_array(dev, prop, events, *n_events);
296+
if (ret)
297+
return ret;
298+
299+
for (ev = 0; ev < *n_events; ev++) {
300+
if (!reset_ev && events[ev] == ADP5589_UNLOCK_WILDCARD)
301+
continue;
302+
303+
if (adp5585->id == ADP5585_MAN_ID_VALUE)
304+
ret = adp5585_validate_event(adp5585, events[ev]);
305+
else
306+
ret = adp5589_validate_event(adp5585, events[ev]);
307+
if (ret)
308+
return ret;
309+
}
310+
311+
return 0;
312+
}
313+
314+
static int adp5585_unlock_ev_parse(struct adp5585_dev *adp5585)
315+
{
316+
struct device *dev = adp5585->dev;
317+
int ret;
318+
319+
ret = adp5585_parse_ev_array(adp5585, "adi,unlock-events", adp5585->unlock_keys,
320+
&adp5585->nkeys_unlock, ARRAY_SIZE(adp5585->unlock_keys),
321+
false);
322+
if (ret)
323+
return ret;
324+
if (!adp5585->nkeys_unlock)
325+
return 0;
326+
327+
ret = device_property_read_u32(dev, "adi,unlock-trigger-sec", &adp5585->unlock_time);
328+
if (!ret) {
329+
if (adp5585->unlock_time > ADP5585_MAX_UNLOCK_TIME_SEC)
330+
return dev_err_probe(dev, -EINVAL,
331+
"Invalid unlock time(%u > %d)\n",
332+
adp5585->unlock_time,
333+
ADP5585_MAX_UNLOCK_TIME_SEC);
334+
}
335+
336+
return 0;
337+
}
338+
339+
static int adp5585_reset_ev_parse(struct adp5585_dev *adp5585)
340+
{
341+
struct device *dev = adp5585->dev;
342+
u32 prop_val;
343+
int ret;
344+
345+
ret = adp5585_parse_ev_array(adp5585, "adi,reset1-events", adp5585->reset1_keys,
346+
&adp5585->nkeys_reset1,
347+
ARRAY_SIZE(adp5585->reset1_keys), true);
348+
if (ret)
349+
return ret;
350+
351+
ret = adp5585_parse_ev_array(adp5585, "adi,reset2-events",
352+
adp5585->reset2_keys,
353+
&adp5585->nkeys_reset2,
354+
ARRAY_SIZE(adp5585->reset2_keys), true);
355+
if (ret)
356+
return ret;
357+
358+
if (!adp5585->nkeys_reset1 && !adp5585->nkeys_reset2)
359+
return 0;
360+
361+
if (adp5585->nkeys_reset1 && device_property_read_bool(dev, "adi,reset1-active-high"))
362+
adp5585->reset_cfg |= FIELD_PREP(ADP5585_RESET1_POL, 1);
363+
364+
if (adp5585->nkeys_reset2 && device_property_read_bool(dev, "adi,reset2-active-high"))
365+
adp5585->reset_cfg |= FIELD_PREP(ADP5585_RESET2_POL, 1);
366+
367+
if (device_property_read_bool(dev, "adi,rst-passthrough-enable"))
368+
adp5585->reset_cfg |= FIELD_PREP(ADP5585_RST_PASSTHRU_EN, 1);
369+
370+
ret = device_property_read_u32(dev, "adi,reset-trigger-ms", &prop_val);
371+
if (!ret) {
372+
switch (prop_val) {
373+
case 0:
374+
adp5585->reset_cfg |= FIELD_PREP(ADP5585_RESET_TRIG_TIME, 0);
375+
break;
376+
case 1000:
377+
adp5585->reset_cfg |= FIELD_PREP(ADP5585_RESET_TRIG_TIME, 1);
378+
break;
379+
case 1500:
380+
adp5585->reset_cfg |= FIELD_PREP(ADP5585_RESET_TRIG_TIME, 2);
381+
break;
382+
case 2000:
383+
adp5585->reset_cfg |= FIELD_PREP(ADP5585_RESET_TRIG_TIME, 3);
384+
break;
385+
case 2500:
386+
adp5585->reset_cfg |= FIELD_PREP(ADP5585_RESET_TRIG_TIME, 4);
387+
break;
388+
case 3000:
389+
adp5585->reset_cfg |= FIELD_PREP(ADP5585_RESET_TRIG_TIME, 5);
390+
break;
391+
case 3500:
392+
adp5585->reset_cfg |= FIELD_PREP(ADP5585_RESET_TRIG_TIME, 6);
393+
break;
394+
case 4000:
395+
adp5585->reset_cfg |= FIELD_PREP(ADP5585_RESET_TRIG_TIME, 7);
396+
break;
397+
default:
398+
return dev_err_probe(dev, -EINVAL,
399+
"Invalid value(%u) for adi,reset-trigger-ms\n",
400+
prop_val);
401+
}
402+
}
403+
404+
ret = device_property_read_u32(dev, "adi,reset-pulse-width-us", &prop_val);
405+
if (!ret) {
406+
switch (prop_val) {
407+
case 500:
408+
adp5585->reset_cfg |= FIELD_PREP(ADP5585_PULSE_WIDTH, 0);
409+
break;
410+
case 1000:
411+
adp5585->reset_cfg |= FIELD_PREP(ADP5585_PULSE_WIDTH, 1);
412+
break;
413+
case 2000:
414+
adp5585->reset_cfg |= FIELD_PREP(ADP5585_PULSE_WIDTH, 2);
415+
break;
416+
case 10000:
417+
adp5585->reset_cfg |= FIELD_PREP(ADP5585_PULSE_WIDTH, 3);
418+
break;
419+
default:
420+
return dev_err_probe(dev, -EINVAL,
421+
"Invalid value(%u) for adi,reset-pulse-width-us\n",
422+
prop_val);
423+
}
424+
return ret;
425+
}
426+
427+
return 0;
428+
}
429+
216430
static int adp5585_add_devices(const struct adp5585_dev *adp5585)
217431
{
218432
struct device *dev = adp5585->dev;
@@ -301,9 +515,61 @@ static irqreturn_t adp5585_irq(int irq, void *data)
301515
static int adp5585_setup(struct adp5585_dev *adp5585)
302516
{
303517
const struct adp5585_regs *regs = adp5585->regs;
304-
unsigned int reg_val, i;
518+
unsigned int reg_val = 0, i;
305519
int ret;
306520

521+
/* Configure the device with reset and unlock events */
522+
for (i = 0; i < adp5585->nkeys_unlock; i++) {
523+
ret = regmap_write(adp5585->regmap, ADP5589_UNLOCK1 + i,
524+
adp5585->unlock_keys[i] | ADP5589_UNLOCK_EV_PRESS);
525+
if (ret)
526+
return ret;
527+
}
528+
529+
if (adp5585->nkeys_unlock) {
530+
ret = regmap_update_bits(adp5585->regmap, ADP5589_UNLOCK_TIMERS,
531+
ADP5589_UNLOCK_TIMER, adp5585->unlock_time);
532+
if (ret)
533+
return ret;
534+
535+
ret = regmap_set_bits(adp5585->regmap, ADP5589_LOCK_CFG, ADP5589_LOCK_EN);
536+
if (ret)
537+
return ret;
538+
}
539+
540+
for (i = 0; i < adp5585->nkeys_reset1; i++) {
541+
ret = regmap_write(adp5585->regmap, regs->reset1_event_a + i,
542+
adp5585->reset1_keys[i] | ADP5585_RESET_EV_PRESS);
543+
if (ret)
544+
return ret;
545+
}
546+
547+
for (i = 0; i < adp5585->nkeys_reset2; i++) {
548+
ret = regmap_write(adp5585->regmap, regs->reset2_event_a + i,
549+
adp5585->reset2_keys[i] | ADP5585_RESET_EV_PRESS);
550+
if (ret)
551+
return ret;
552+
}
553+
554+
if (adp5585->nkeys_reset1 || adp5585->nkeys_reset2) {
555+
ret = regmap_write(adp5585->regmap, regs->reset_cfg, adp5585->reset_cfg);
556+
if (ret)
557+
return ret;
558+
559+
/* If there's a reset1 event, then R4 is used as an output for the reset signal */
560+
if (adp5585->nkeys_reset1)
561+
reg_val = ADP5585_R4_EXTEND_CFG_RESET1;
562+
/* If there's a reset2 event, then C4 is used as an output for the reset signal */
563+
if (adp5585->nkeys_reset2)
564+
reg_val |= ADP5585_C4_EXTEND_CFG_RESET2;
565+
566+
ret = regmap_update_bits(adp5585->regmap, regs->ext_cfg,
567+
ADP5585_C4_EXTEND_CFG_MASK | ADP5585_R4_EXTEND_CFG_MASK,
568+
reg_val);
569+
if (ret)
570+
return ret;
571+
}
572+
307573
/* Clear any possible event by reading all the FIFO entries */
308574
for (i = 0; i < ADP5585_EV_MAX; i++) {
309575
ret = regmap_read(adp5585->regmap, ADP5585_FIFO_1 + i, &reg_val);
@@ -344,7 +610,11 @@ static int adp5585_parse_fw(struct adp5585_dev *adp5585)
344610
"Invalid value(%u) for poll-interval\n", prop_val);
345611
}
346612

347-
return 0;
613+
ret = adp5585_unlock_ev_parse(adp5585);
614+
if (ret)
615+
return ret;
616+
617+
return adp5585_reset_ev_parse(adp5585);
348618
}
349619

350620
static void adp5585_irq_disable(void *data)

0 commit comments

Comments
 (0)