From 9df731a176aab8e03b984b681b1bea01ccff6644 Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Mon, 06 Nov 2023 07:23:06 +0000 Subject: [PATCH] rk3568 rt uboot init --- u-boot/drivers/input/spl_adc_key.c | 141 ++++++++++++++++++++++++++++++++++------------ 1 files changed, 103 insertions(+), 38 deletions(-) diff --git a/u-boot/drivers/input/spl_adc_key.c b/u-boot/drivers/input/spl_adc_key.c index 60e0394..8aceaef 100644 --- a/u-boot/drivers/input/spl_adc_key.c +++ b/u-boot/drivers/input/spl_adc_key.c @@ -6,28 +6,46 @@ #include <common.h> #include <adc.h> +#include <div64.h> #include <fdtdec.h> +#include <dm/uclass.h> DECLARE_GLOBAL_DATA_PTR; + +static int adc_raw_to_mV(struct udevice *dev, unsigned int raw, int *mV) +{ + unsigned int data_mask; + int ret, vref = 1800000; + u64 raw64 = raw; + + ret = adc_data_mask(dev, &data_mask); + if (ret) + return ret; + + raw64 *= vref; + do_div(raw64, data_mask); + *mV = raw64; + + return 0; +} int key_read(int code) { const void *fdt_blob = gd->fdt_blob; + struct udevice *dev; int adc_node, offset; - int cd, channel, adc; - int ret, vref, mv; + int t, down_threshold = -1, up_threshold; + int ret, num = 0, volt_margin = 150000; /* will be div 2 */ + int mV, cd, voltage = -1; int min, max; - int margin; - int range; - uint val; - u32 chn[2]; -#ifdef CONFIG_SARADC_ROCKCHIP_V2 - range = 4096; /* 12-bit adc */ - margin = 120; -#else - range = 1024; /* 10-bit adc */ - margin = 30; -#endif + u32 chn[2], adc; + + ret = uclass_get_device_by_name(UCLASS_ADC, "saradc", &dev); + if (ret) { + debug("No saradc device, ret=%d\n", ret); + return 0; + } + adc_node = fdt_node_offset_by_compatible(fdt_blob, 0, "adc-keys"); if (adc_node < 0) { debug("No 'adc-keys' node, ret=%d\n", adc_node); @@ -41,40 +59,87 @@ return 0; } - vref = fdtdec_get_int(fdt_blob, adc_node, - "keyup-threshold-microvolt", -1); - if (vref < 0) { + up_threshold = fdtdec_get_int(fdt_blob, adc_node, + "keyup-threshold-microvolt", -ENODATA); + if (up_threshold < 0) { debug("Can't read 'keyup-threshold-microvolt'\n"); return 0; } - channel = chn[1]; + /* find the expected key-code */ + for (offset = fdt_first_subnode(fdt_blob, adc_node); + offset >= 0; + offset = fdt_next_subnode(fdt_blob, offset)) { + cd = fdtdec_get_int(fdt_blob, offset, "linux,code", -ENODATA); + if (cd < 0) { + debug("Can't read 'linux,code', ret=%d\n", cd); + return 0; + } + + if (cd == code) { + voltage = fdtdec_get_int(fdt_blob, offset, + "press-threshold-microvolt", -ENODATA); + if (voltage < 0) { + debug("Can't read 'press-threshold-microvolt'\n"); + return 0; + } + break; + } + } + + if (voltage < 0) + return 0; for (offset = fdt_first_subnode(fdt_blob, adc_node); offset >= 0; offset = fdt_next_subnode(fdt_blob, offset)) { - cd = fdtdec_get_int(fdt_blob, offset, "linux,code", -1); - if (cd == code) { - mv = fdtdec_get_int(fdt_blob, offset, - "press-threshold-microvolt", -1); - if (mv < 0) { - debug("Can't read 'press-threshold-microvolt'\n"); - return 0; - } - - adc = mv / (vref / range); - max = adc + margin; - min = adc > margin ? adc - margin : 0; - ret = adc_channel_single_shot("saradc", channel, &val); - if (ret) { - debug("Failed to read adc%d, ret=%d\n", - channel, ret); - return 0; - } - - return (val >= min && val <= max); + t = fdtdec_get_int(fdt_blob, offset, + "press-threshold-microvolt", -ENODATA); + if (t < 0) { + debug("Can't read 'press-threshold-microvolt'\n"); + return 0; } + + if (t > voltage && t < up_threshold) + up_threshold = t; + else if (t < voltage && t > down_threshold) + down_threshold = t; + num++; } - return 0; + /* although one node only, it doesn't mean only one key on hardware */ + if (num == 1) { + down_threshold = voltage - volt_margin; + up_threshold = voltage + volt_margin; + } + + /* + * Define the voltage range such that the button is only pressed + * when the voltage is closest to its own press-threshold-microvolt + */ + if (down_threshold < 0) + min = 0; + else + min = down_threshold + (voltage - down_threshold) / 2; + + max = voltage + (up_threshold - voltage) / 2; + + /* now, read key status */ + ret = adc_channel_single_shot("saradc", chn[1], &adc); + if (ret) { + debug("Failed to read adc%d, ret=%d\n", chn[1], ret); + return 0; + } + + ret = adc_raw_to_mV(dev, adc, &mV); + if (ret) { + debug("Failed to convert adc to mV, ret=%d\n", ret); + return 0; + } + + debug("key[%d] <%d, %d, %d>: adc=%d -> mV=%d\n", + code, min, voltage, max, adc, mV); + + return (mV <= max && mV >= min); } + -- Gitblit v1.6.2