mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-10 23:24:38 +00:00
- adds adc-keys button driver
- fix meson-saradc driver to get reference voltage - add adc-keys test for sandbox - enable adc-keys for VIM3 & VIM3L boards - fix button.h build -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEPVPGJshWBf4d9CyLd9zb2sjISdEFAmAzv0gACgkQd9zb2sjI SdGUaw//ZeWLd5uVOIb7lWW/LyEM8gjll3SGm40YMvxucBkb3tYyQzWpInUDAua0 +rOpXptlCZ6WMfTJ2PhB0e30aZexgN3XsvHYEMEV7MGmk1HoUfqGHiDWcI1pDLD0 p8cmoNoDYWDUqj1J1ibUUOjK+SrAXjezp+kxSjP0ttpXX2RxhXEZrFwzSK6uqUZk acqLwg+dOZZLtYZb1gYiDu2NHxnLEqRGqoG/D5emKjZQ3Ofquw+/TFawWpZH5qZf cRWCtEo8b9QMdgkI9wvgTHPfPGIP3mkRfQpGrhUmtDsX15s3VVIsEDtjmLluXn6P TjVocElz2BrsYENFLo7vt/V7A7MQ6n/276y3H6hyzPwM/LMPLWUsSowiYPVgfXzy td8f5NgH8996LN79ia8ZlVYeV3XJu1w26l7kSfBpybS1HVXNTSCsHy5a9y2vjl1B YH2O8i7yLxwld/ce0oQtu+6SiFaKWBUdc1FQXOvXeYy89VsRqvaS7RMI2yF3GCcb Ov38QVkq2hWIyz4CfpyKtXGSr/H7tOtQdEi9eAMeJwbBprMh/fjpeI8M0QAGdAW0 F5jUFHK4+BFlqOFphTb00SYLFPCBRfK4kwg2azfQs4589ShlcLaY1RkGRsezLCj2 bqwITNC+bLup5MSseBr/CgMaXR7JMxbYOuYlLupzRyo5yI0MWvo= =/PJV -----END PGP SIGNATURE----- Merge tag 'u-boot-amlogic-20210222' of https://gitlab.denx.de/u-boot/custodians/u-boot-amlogic - adds adc-keys button driver - fix meson-saradc driver to get reference voltage - add adc-keys test for sandbox - enable adc-keys for VIM3 & VIM3L boards - fix button.h build
This commit is contained in:
commit
8f7a16aac3
11 changed files with 325 additions and 3 deletions
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/gpio/sandbox-gpio.h>
|
||||
#include <dt-bindings/input/input.h>
|
||||
#include <dt-bindings/pinctrl/sandbox-pinmux.h>
|
||||
#include <dt-bindings/mux/mux.h>
|
||||
|
||||
|
@ -69,6 +70,30 @@
|
|||
};
|
||||
};
|
||||
|
||||
buttons2 {
|
||||
compatible = "adc-keys";
|
||||
io-channels = <&adc 3>;
|
||||
keyup-threshold-microvolt = <3000000>;
|
||||
|
||||
button-up {
|
||||
label = "button3";
|
||||
linux,code = <KEY_F3>;
|
||||
press-threshold-microvolt = <1500000>;
|
||||
};
|
||||
|
||||
button-down {
|
||||
label = "button4";
|
||||
linux,code = <KEY_F4>;
|
||||
press-threshold-microvolt = <1000000>;
|
||||
};
|
||||
|
||||
button-enter {
|
||||
label = "button5";
|
||||
linux,code = <KEY_F5>;
|
||||
press-threshold-microvolt = <500000>;
|
||||
};
|
||||
};
|
||||
|
||||
cros_ec: cros-ec {
|
||||
reg = <0 0>;
|
||||
compatible = "google,cros-ec-sandbox";
|
||||
|
@ -608,8 +633,9 @@
|
|||
i2c-eeprom = <&bootcount_i2c>;
|
||||
};
|
||||
|
||||
adc@0 {
|
||||
adc: adc@0 {
|
||||
compatible = "sandbox,adc";
|
||||
#io-channel-cells = <1>;
|
||||
vdd-supply = <&buck2>;
|
||||
vss-microvolts = <0>;
|
||||
};
|
||||
|
|
|
@ -31,6 +31,8 @@ CONFIG_SYS_RELOC_GD_ENV_ADDR=y
|
|||
CONFIG_NET_RANDOM_ETHADDR=y
|
||||
CONFIG_ADC=y
|
||||
CONFIG_SARADC_MESON=y
|
||||
CONFIG_BUTTON=y
|
||||
CONFIG_BUTTON_ADC=y
|
||||
CONFIG_DM_I2C=y
|
||||
CONFIG_SYS_I2C_MESON=y
|
||||
CONFIG_DM_MMC=y
|
||||
|
|
|
@ -31,6 +31,8 @@ CONFIG_SYS_RELOC_GD_ENV_ADDR=y
|
|||
CONFIG_NET_RANDOM_ETHADDR=y
|
||||
CONFIG_ADC=y
|
||||
CONFIG_SARADC_MESON=y
|
||||
CONFIG_BUTTON=y
|
||||
CONFIG_BUTTON_ADC=y
|
||||
CONFIG_DM_I2C=y
|
||||
CONFIG_SYS_I2C_MESON=y
|
||||
CONFIG_DM_MMC=y
|
||||
|
|
|
@ -123,6 +123,7 @@ CONFIG_DM_BOOTCOUNT=y
|
|||
CONFIG_DM_BOOTCOUNT_RTC=y
|
||||
CONFIG_DM_BOOTCOUNT_I2C_EEPROM=y
|
||||
CONFIG_BUTTON=y
|
||||
CONFIG_BUTTON_ADC=y
|
||||
CONFIG_BUTTON_GPIO=y
|
||||
CONFIG_CLK=y
|
||||
CONFIG_CLK_COMPOSITE_CCF=y
|
||||
|
|
67
doc/device-tree-bindings/input/adc-keys.txt
Normal file
67
doc/device-tree-bindings/input/adc-keys.txt
Normal file
|
@ -0,0 +1,67 @@
|
|||
ADC attached resistor ladder buttons
|
||||
------------------------------------
|
||||
|
||||
Required properties:
|
||||
- compatible: "adc-keys"
|
||||
- io-channels: Phandle to an ADC channel
|
||||
- io-channel-names = "buttons";
|
||||
- keyup-threshold-microvolt: Voltage above or equal to which all the keys are
|
||||
considered up.
|
||||
|
||||
Optional properties:
|
||||
- poll-interval: Poll interval time in milliseconds
|
||||
- autorepeat: Boolean, Enable auto repeat feature of Linux input
|
||||
subsystem.
|
||||
|
||||
Each button (key) is represented as a sub-node of "adc-keys":
|
||||
|
||||
Required subnode-properties:
|
||||
- label: Descriptive name of the key.
|
||||
- linux,code: Keycode to emit.
|
||||
- press-threshold-microvolt: voltage above or equal to which this key is
|
||||
considered pressed.
|
||||
|
||||
No two values of press-threshold-microvolt may be the same.
|
||||
All values of press-threshold-microvolt must be less than
|
||||
keyup-threshold-microvolt.
|
||||
|
||||
Example:
|
||||
|
||||
#include <dt-bindings/input/input.h>
|
||||
|
||||
adc-keys {
|
||||
compatible = "adc-keys";
|
||||
io-channels = <&lradc 0>;
|
||||
io-channel-names = "buttons";
|
||||
keyup-threshold-microvolt = <2000000>;
|
||||
|
||||
button-up {
|
||||
label = "Volume Up";
|
||||
linux,code = <KEY_VOLUMEUP>;
|
||||
press-threshold-microvolt = <1500000>;
|
||||
};
|
||||
|
||||
button-down {
|
||||
label = "Volume Down";
|
||||
linux,code = <KEY_VOLUMEDOWN>;
|
||||
press-threshold-microvolt = <1000000>;
|
||||
};
|
||||
|
||||
button-enter {
|
||||
label = "Enter";
|
||||
linux,code = <KEY_ENTER>;
|
||||
press-threshold-microvolt = <500000>;
|
||||
};
|
||||
};
|
||||
|
||||
+--------------------------------+------------------------+
|
||||
| 2.000.000 <= value | no key pressed |
|
||||
+--------------------------------+------------------------+
|
||||
| 1.500.000 <= value < 2.000.000 | KEY_VOLUMEUP pressed |
|
||||
+--------------------------------+------------------------+
|
||||
| 1.000.000 <= value < 1.500.000 | KEY_VOLUMEDOWN pressed |
|
||||
+--------------------------------+------------------------+
|
||||
| 500.000 <= value < 1.000.000 | KEY_ENTER pressed |
|
||||
+--------------------------------+------------------------+
|
||||
| value < 500.000 | no key pressed |
|
||||
+--------------------------------+------------------------+
|
|
@ -18,6 +18,7 @@
|
|||
#include <linux/delay.h>
|
||||
#include <linux/math64.h>
|
||||
#include <linux/bitfield.h>
|
||||
#include <power/regulator.h>
|
||||
|
||||
#define MESON_SAR_ADC_REG0 0x00
|
||||
#define MESON_SAR_ADC_REG0_PANEL_DETECT BIT(31)
|
||||
|
@ -656,7 +657,10 @@ static int meson_saradc_stop(struct udevice *dev)
|
|||
|
||||
static int meson_saradc_probe(struct udevice *dev)
|
||||
{
|
||||
struct adc_uclass_plat *uc_pdata = dev_get_uclass_plat(dev);
|
||||
struct meson_saradc_priv *priv = dev_get_priv(dev);
|
||||
struct udevice *vref;
|
||||
int vref_uv;
|
||||
int ret;
|
||||
|
||||
ret = regmap_init_mem(dev_ofnode(dev), &priv->regmap);
|
||||
|
@ -675,6 +679,23 @@ static int meson_saradc_probe(struct udevice *dev)
|
|||
|
||||
priv->active_channel = -1;
|
||||
|
||||
ret = device_get_supply_regulator(dev, "vref-supply", &vref);
|
||||
if (ret) {
|
||||
printf("can't get vref-supply: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
vref_uv = regulator_get_value(vref);
|
||||
if (vref_uv < 0) {
|
||||
printf("can't get vref-supply value: %d\n", vref_uv);
|
||||
return vref_uv;
|
||||
}
|
||||
|
||||
/* VDD supplied by common vref pin */
|
||||
uc_pdata->vdd_supply = vref;
|
||||
uc_pdata->vdd_microvolts = vref_uv;
|
||||
uc_pdata->vss_microvolts = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 Analog to Digital
|
||||
Converter device. The ADC driver must use driver model. Buttons are
|
||||
configured using the device tree.
|
||||
|
||||
config BUTTON_GPIO
|
||||
bool "Button gpio"
|
||||
depends on BUTTON
|
||||
|
|
|
@ -3,4 +3,5 @@
|
|||
# Copyright (C) 2020 Philippe Reynes <philippe.reynes@softathome.com>
|
||||
|
||||
obj-$(CONFIG_BUTTON) += button-uclass.o
|
||||
obj-$(CONFIG_BUTTON_ADC) += button-adc.o
|
||||
obj-$(CONFIG_BUTTON_GPIO) += button-gpio.o
|
||||
|
|
146
drivers/button/button-adc.c
Normal file
146
drivers/button/button-adc.c
Normal file
|
@ -0,0 +1,146 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) 2021 Samsung Electronics Co., Ltd.
|
||||
* http://www.samsung.com
|
||||
* Author: Marek Szyprowski <m.szyprowski@samsung.com>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <adc.h>
|
||||
#include <button.h>
|
||||
#include <log.h>
|
||||
#include <dm.h>
|
||||
#include <dm/lists.h>
|
||||
#include <dm/of_access.h>
|
||||
#include <dm/uclass-internal.h>
|
||||
|
||||
/**
|
||||
* struct button_adc_priv - private data for button-adc driver.
|
||||
*
|
||||
* @adc: Analog to Digital Converter device to which button is connected.
|
||||
* @channel: channel of the ADC device to probe the button state.
|
||||
* @min: minimal uV value to consider button as pressed.
|
||||
* @max: maximal uV value to consider button as pressed.
|
||||
*/
|
||||
struct button_adc_priv {
|
||||
struct udevice *adc;
|
||||
int channel;
|
||||
int min;
|
||||
int max;
|
||||
};
|
||||
|
||||
static enum button_state_t button_adc_get_state(struct udevice *dev)
|
||||
{
|
||||
struct button_adc_priv *priv = dev_get_priv(dev);
|
||||
unsigned int val;
|
||||
int ret, uV;
|
||||
|
||||
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_raw_to_uV(priv->adc, val, &uV);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return (uV >= priv->min && uV < priv->max) ? BUTTON_ON : BUTTON_OFF;
|
||||
}
|
||||
|
||||
static int button_adc_of_to_plat(struct udevice *dev)
|
||||
{
|
||||
struct button_uc_plat *uc_plat = dev_get_uclass_plat(dev);
|
||||
struct button_adc_priv *priv = dev_get_priv(dev);
|
||||
struct ofnode_phandle_args args;
|
||||
u32 treshold, up_treshold, t;
|
||||
ofnode node;
|
||||
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_ofnode(UCLASS_ADC, args.node, &priv->adc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ofnode_read_u32(dev_ofnode(dev->parent),
|
||||
"keyup-threshold-microvolt", &up_treshold);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ofnode_read_u32(dev_ofnode(dev), "press-threshold-microvolt",
|
||||
&treshold);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dev_for_each_subnode(node, dev->parent) {
|
||||
ret = ofnode_read_u32(node, "press-threshold-microvolt", &t);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (t > treshold)
|
||||
up_treshold = t;
|
||||
}
|
||||
|
||||
priv->channel = args.args[0];
|
||||
priv->min = treshold;
|
||||
priv->max = up_treshold;
|
||||
|
||||
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_plat(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 = sizeof(struct button_adc_priv),
|
||||
.bind = button_adc_bind,
|
||||
.of_to_plat = button_adc_of_to_plat,
|
||||
};
|
|
@ -6,6 +6,8 @@
|
|||
#ifndef __BUTTON_H
|
||||
#define __BUTTON_H
|
||||
|
||||
struct udevice;
|
||||
|
||||
/**
|
||||
* struct button_uc_plat - Platform data the uclass stores about each device
|
||||
*
|
||||
|
|
|
@ -7,7 +7,10 @@
|
|||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <adc.h>
|
||||
#include <button.h>
|
||||
#include <power/regulator.h>
|
||||
#include <power/sandbox_pmic.h>
|
||||
#include <asm/gpio.h>
|
||||
#include <dm/test.h>
|
||||
#include <test/ut.h>
|
||||
|
@ -17,11 +20,20 @@ static int dm_test_button_base(struct unit_test_state *uts)
|
|||
{
|
||||
struct udevice *dev;
|
||||
|
||||
/* Get the top-level device */
|
||||
/* Get the top-level gpio buttons device */
|
||||
ut_assertok(uclass_get_device(UCLASS_BUTTON, 0, &dev));
|
||||
/* Get the 2 gpio buttons */
|
||||
ut_assertok(uclass_get_device(UCLASS_BUTTON, 1, &dev));
|
||||
ut_assertok(uclass_get_device(UCLASS_BUTTON, 2, &dev));
|
||||
ut_asserteq(-ENODEV, uclass_get_device(UCLASS_BUTTON, 3, &dev));
|
||||
|
||||
/* Get the top-level adc buttons device */
|
||||
ut_assertok(uclass_get_device(UCLASS_BUTTON, 3, &dev));
|
||||
/* Get the 3 adc buttons */
|
||||
ut_assertok(uclass_get_device(UCLASS_BUTTON, 4, &dev));
|
||||
ut_assertok(uclass_get_device(UCLASS_BUTTON, 5, &dev));
|
||||
ut_assertok(uclass_get_device(UCLASS_BUTTON, 6, &dev));
|
||||
|
||||
ut_asserteq(-ENODEV, uclass_get_device(UCLASS_BUTTON, 7, &dev));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -72,3 +84,37 @@ static int dm_test_button_label(struct unit_test_state *uts)
|
|||
return 0;
|
||||
}
|
||||
DM_TEST(dm_test_button_label, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
|
||||
|
||||
/* Test adc-keys driver */
|
||||
static int dm_test_button_keys_adc(struct unit_test_state *uts)
|
||||
{
|
||||
struct udevice *supply;
|
||||
struct udevice *dev;
|
||||
int uV;
|
||||
|
||||
ut_assertok(uclass_get_device_by_name(UCLASS_ADC, "adc@0", &dev));
|
||||
|
||||
ut_assertok(regulator_get_by_devname(SANDBOX_BUCK2_DEVNAME, &supply));
|
||||
ut_assertok(regulator_set_value(supply, SANDBOX_BUCK2_SET_UV));
|
||||
ut_asserteq(SANDBOX_BUCK2_SET_UV, regulator_get_value(supply));
|
||||
/* Update ADC plat and get new Vdd value */
|
||||
ut_assertok(adc_vdd_value(dev, &uV));
|
||||
ut_asserteq(SANDBOX_BUCK2_SET_UV, uV);
|
||||
|
||||
/*
|
||||
* sandbox-adc returns constant value on channel 3, is used by adc-keys:
|
||||
* SANDBOX_ADC_CHANNEL3_DATA * SANDBOX_BUCK2_SET_UV / SANDBOX_ADC_DATA_MASK =
|
||||
* 0x3000 * 3300000 / 0xffff = 618759uV
|
||||
* This means that button3 and button4 are released and button5
|
||||
* is pressed.
|
||||
*/
|
||||
ut_assertok(button_get_by_label("button3", &dev));
|
||||
ut_asserteq(BUTTON_OFF, button_get_state(dev));
|
||||
ut_assertok(button_get_by_label("button4", &dev));
|
||||
ut_asserteq(BUTTON_OFF, button_get_state(dev));
|
||||
ut_assertok(button_get_by_label("button5", &dev));
|
||||
ut_asserteq(BUTTON_ON, button_get_state(dev));
|
||||
|
||||
return 0;
|
||||
}
|
||||
DM_TEST(dm_test_button_keys_adc, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);
|
||||
|
|
Loading…
Reference in a new issue