[PATCH v2 5/7] button: add a simple ADC-based button driver
Heinrich Schuchardt
xypron.glpk at gmx.de
Tue Dec 15 20:19:00 CET 2020
On 12/15/20 3:42 PM, Marek Szyprowski wrote:
> Add a simple ADC-based button driver. This driver binds to the 'adc-keys'
> device tree node.
>
> Signed-off-by: Marek Szyprowski <m.szyprowski at samsung.com>
> ---
> drivers/button/Kconfig | 8 +++
> drivers/button/Makefile | 1 +
> drivers/button/button-adc.c | 117 ++++++++++++++++++++++++++++++++++++
> 3 files changed, 126 insertions(+)
> create mode 100644 drivers/button/button-adc.c
>
> diff --git a/drivers/button/Kconfig b/drivers/button/Kconfig
> index 6b3ec7e55d..283367f2bd 100644
> --- a/drivers/button/Kconfig
> +++ b/drivers/button/Kconfig
> @@ -9,6 +9,14 @@ config BUTTON
> can provide access to board-specific buttons. Use of the device tree
> for configuration is encouraged.
>
> +config BUTTON_ADC
> + bool "Button adc"
> + depends on BUTTON
> + help
> + Enable support for buttons which are connected to ADC lines. The ADC
ADC might stand for "Analog to Digital Converter", or "Automated Data
Collection", or "Automatic Distance Control, or something else. Please,
replace the abbreviation by the full expression.
Best regards
Heinrich
> + driver must use driver model. Buttons are configured using the device
> + tree.
> +
> config BUTTON_GPIO
> bool "Button gpio"
> depends on BUTTON
> diff --git a/drivers/button/Makefile b/drivers/button/Makefile
> index fcc10ebe8d..bbd18af149 100644
> --- a/drivers/button/Makefile
> +++ b/drivers/button/Makefile
> @@ -3,4 +3,5 @@
> # Copyright (C) 2020 Philippe Reynes <philippe.reynes at softathome.com>
>
> obj-$(CONFIG_BUTTON) += button-uclass.o
> +obj-$(CONFIG_BUTTON_ADC) += button-adc.o
> obj-$(CONFIG_BUTTON_GPIO) += button-gpio.o
> diff --git a/drivers/button/button-adc.c b/drivers/button/button-adc.c
> new file mode 100644
> index 0000000000..086c676c02
> --- /dev/null
> +++ b/drivers/button/button-adc.c
> @@ -0,0 +1,117 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2020 Samsung Electronics Co., Ltd.
> + * http://www.samsung.com
> + * Author: Marek Szyprowski <m.szyprowski at samsung.com>
> + */
> +
> +#include <common.h>
> +#include <button.h>
> +#include <dm.h>
> +#include <dm/lists.h>
> +#include <dm/uclass-internal.h>
> +#include <log.h>
> +#include <adc.h>
> +
> +struct button_adc_priv {
> + struct udevice *adc;
> + int channel;
> +};
> +
> +static enum button_state_t button_adc_get_state(struct udevice *dev)
> +{
> + struct button_adc_priv *priv = dev_get_priv(dev);
> + unsigned int val, mask;
> + int ret;
> +
> + ret = adc_start_channel(priv->adc, priv->channel);
> + if (ret)
> + return ret;
> +
> + ret = adc_channel_data(priv->adc, priv->channel, &val);
> + if (ret)
> + return ret;
> +
> + ret = adc_data_mask(priv->adc, &mask);
> + if (ret)
> + return ret;
> +
> + /* getting state is simplified a bit */
> + if (ret == 0)
> + return (val < mask / 2) ? BUTTON_ON : BUTTON_OFF;
> +
> + return ret;
> +}
> +
> +static int button_adc_probe(struct udevice *dev)
> +{
> + struct button_uc_plat *uc_plat = dev_get_uclass_platdata(dev);
> + struct button_adc_priv *priv = dev_get_priv(dev);
> + struct ofnode_phandle_args args;
> + int ret;
> +
> + /* Ignore the top-level button node */
> + if (!uc_plat->label)
> + return 0;
> +
> + ret = dev_read_phandle_with_args(dev->parent, "io-channels",
> + "#io-channel-cells", 0, 0, &args);
> + if (ret)
> + return ret;
> +
> + ret = uclass_get_device_by_name(UCLASS_ADC, ofnode_get_name(args.node),
> + &priv->adc);
> + if (ret)
> + return ret;
> +
> + priv->channel = args.args[0];
> +
> + return ret;
> +}
> +
> +static int button_adc_bind(struct udevice *parent)
> +{
> + struct udevice *dev;
> + ofnode node;
> + int ret;
> +
> + dev_for_each_subnode(node, parent) {
> + struct button_uc_plat *uc_plat;
> + const char *label;
> +
> + label = ofnode_read_string(node, "label");
> + if (!label) {
> + debug("%s: node %s has no label\n", __func__,
> + ofnode_get_name(node));
> + return -EINVAL;
> + }
> + ret = device_bind_driver_to_node(parent, "button_adc",
> + ofnode_get_name(node),
> + node, &dev);
> + if (ret)
> + return ret;
> + uc_plat = dev_get_uclass_platdata(dev);
> + uc_plat->label = label;
> + }
> +
> + return 0;
> +}
> +
> +static const struct button_ops button_adc_ops = {
> + .get_state = button_adc_get_state,
> +};
> +
> +static const struct udevice_id button_adc_ids[] = {
> + { .compatible = "adc-keys" },
> + { }
> +};
> +
> +U_BOOT_DRIVER(button_adc) = {
> + .name = "button_adc",
> + .id = UCLASS_BUTTON,
> + .of_match = button_adc_ids,
> + .ops = &button_adc_ops,
> + .priv_auto_alloc_size = sizeof(struct button_adc_priv),
> + .bind = button_adc_bind,
> + .probe = button_adc_probe,
> +};
>
More information about the U-Boot
mailing list