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