1 // SPDX-License-Identifier: GPL-2.0+
3 * (C) Copyright 2023 Dzmitry Sankouski <dsankouski@gmail.com>
13 #include <dm/device-internal.h>
17 #include <linux/delay.h>
18 #include <linux/input.h>
21 * struct button_kbd_priv - driver private data
23 * @input: input configuration
24 * @button_size: number of buttons found
25 * @old_state: a pointer to old button states array. Used to determine button state change.
27 struct button_kbd_priv
{
28 struct input_config
*input
;
33 static int button_kbd_start(struct udevice
*dev
)
35 struct button_kbd_priv
*priv
= dev_get_priv(dev
);
37 struct udevice
*button_gpio_devp
;
39 uclass_foreach_dev_probe(UCLASS_BUTTON
, button_gpio_devp
) {
40 struct button_uc_plat
*uc_plat
= dev_get_uclass_plat(button_gpio_devp
);
41 /* Ignore the top-level button node */
44 debug("Found button %s #%d - %s, probing...\n",
45 uc_plat
->label
, i
, button_gpio_devp
->name
);
49 priv
->button_size
= i
;
50 priv
->old_state
= calloc(i
, sizeof(int));
55 int button_read_keys(struct input_config
*input
)
57 struct button_kbd_priv
*priv
= dev_get_priv(input
->dev
);
58 struct udevice
*button_gpio_devp
;
61 u32 code
, state
, state_changed
= 0;
63 uclass_id_foreach_dev(UCLASS_BUTTON
, button_gpio_devp
, uc
) {
64 struct button_uc_plat
*uc_plat
= dev_get_uclass_plat(button_gpio_devp
);
65 /* Ignore the top-level button node */
68 code
= button_get_code(button_gpio_devp
);
72 state
= button_get_state(button_gpio_devp
);
73 state_changed
= state
!= priv
->old_state
[i
];
76 debug("%s: %d\n", uc_plat
->label
, code
);
77 priv
->old_state
[i
] = state
;
78 input_add_keycode(input
, code
, state
);
85 static const struct keyboard_ops button_kbd_ops
= {
86 .start
= button_kbd_start
,
89 static int button_kbd_probe(struct udevice
*dev
)
91 struct button_kbd_priv
*priv
= dev_get_priv(dev
);
92 struct keyboard_priv
*uc_priv
= dev_get_uclass_priv(dev
);
93 struct stdio_dev
*sdev
= &uc_priv
->sdev
;
94 struct input_config
*input
= &uc_priv
->input
;
97 input_init(input
, false);
98 input_add_tables(input
, false);
100 /* Register the device. */
103 input
->read_keys
= button_read_keys
;
104 strcpy(sdev
->name
, "button-kbd");
105 ret
= input_stdio_register(sdev
);
107 debug("%s: input_stdio_register() failed\n", __func__
);
114 static const struct udevice_id button_kbd_ids
[] = {
115 { .compatible
= "button-kbd" },
119 U_BOOT_DRIVER(button_kbd
) = {
120 .name
= "button_kbd",
121 .id
= UCLASS_KEYBOARD
,
122 .of_match
= button_kbd_ids
,
123 .ops
= &button_kbd_ops
,
124 .priv_auto
= sizeof(struct button_kbd_priv
),
125 .probe
= button_kbd_probe
,