1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2021 Samsung Electronics Co., Ltd.
4 * http://www.samsung.com
5 * Author: Marek Szyprowski <m.szyprowski@samsung.com>
14 #include <dm/of_access.h>
15 #include <dm/uclass-internal.h>
18 * struct button_adc_priv - private data for button-adc driver.
20 * @adc: Analog to Digital Converter device to which button is connected.
21 * @channel: channel of the ADC device to probe the button state.
22 * @min: minimal uV value to consider button as pressed.
23 * @max: maximal uV value to consider button as pressed.
25 struct button_adc_priv
{
32 static enum button_state_t
button_adc_get_state(struct udevice
*dev
)
34 struct button_adc_priv
*priv
= dev_get_priv(dev
);
38 ret
= adc_start_channel(priv
->adc
, priv
->channel
);
42 ret
= adc_channel_data(priv
->adc
, priv
->channel
, &val
);
46 ret
= adc_raw_to_uV(priv
->adc
, val
, &uV
);
50 return (uV
>= priv
->min
&& uV
< priv
->max
) ? BUTTON_ON
: BUTTON_OFF
;
53 static int button_adc_of_to_plat(struct udevice
*dev
)
55 struct button_uc_plat
*uc_plat
= dev_get_uclass_plat(dev
);
56 struct button_adc_priv
*priv
= dev_get_priv(dev
);
57 struct ofnode_phandle_args args
;
58 u32 threshold
, up_threshold
, t
;
62 /* Ignore the top-level button node */
66 ret
= dev_read_phandle_with_args(dev
->parent
, "io-channels",
67 "#io-channel-cells", 0, 0, &args
);
71 ret
= uclass_get_device_by_ofnode(UCLASS_ADC
, args
.node
, &priv
->adc
);
75 ret
= ofnode_read_u32(dev_ofnode(dev
->parent
),
76 "keyup-threshold-microvolt", &up_threshold
);
80 ret
= ofnode_read_u32(dev_ofnode(dev
), "press-threshold-microvolt",
85 dev_for_each_subnode(node
, dev
->parent
) {
86 ret
= ofnode_read_u32(node
, "press-threshold-microvolt", &t
);
94 priv
->channel
= args
.args
[0];
95 priv
->min
= threshold
;
96 priv
->max
= up_threshold
;
101 static int button_adc_bind(struct udevice
*parent
)
107 dev_for_each_subnode(node
, parent
) {
108 struct button_uc_plat
*uc_plat
;
111 label
= ofnode_read_string(node
, "label");
113 debug("%s: node %s has no label\n", __func__
,
114 ofnode_get_name(node
));
117 ret
= device_bind_driver_to_node(parent
, "button_adc",
118 ofnode_get_name(node
),
122 uc_plat
= dev_get_uclass_plat(dev
);
123 uc_plat
->label
= label
;
129 static const struct button_ops button_adc_ops
= {
130 .get_state
= button_adc_get_state
,
133 static const struct udevice_id button_adc_ids
[] = {
134 { .compatible
= "adc-keys" },
138 U_BOOT_DRIVER(button_adc
) = {
139 .name
= "button_adc",
141 .of_match
= button_adc_ids
,
142 .ops
= &button_adc_ops
,
143 .priv_auto
= sizeof(struct button_adc_priv
),
144 .bind
= button_adc_bind
,
145 .of_to_plat
= button_adc_of_to_plat
,