168ed8338SJoseph Chen /*
268ed8338SJoseph Chen * (C) Copyright 2017 Rockchip Electronics Co., Ltd
368ed8338SJoseph Chen *
468ed8338SJoseph Chen * SPDX-License-Identifier: GPL-2.0+
568ed8338SJoseph Chen */
668ed8338SJoseph Chen
768ed8338SJoseph Chen #include <common.h>
85a54baa7SJoseph Chen #include <dm.h>
968ed8338SJoseph Chen #include <key.h>
1068ed8338SJoseph Chen
adc_key_ofdata_to_platdata(struct udevice * dev)115a54baa7SJoseph Chen static int adc_key_ofdata_to_platdata(struct udevice *dev)
1268ed8338SJoseph Chen {
135a54baa7SJoseph Chen struct dm_key_uclass_platdata *uc_key;
14*15da1b50SJoseph Chen int t, down_threshold = -1, up_threshold;
15*15da1b50SJoseph Chen int ret, num = 0, volt_margin = 150000; /* will be div 2 */
16*15da1b50SJoseph Chen u32 voltage, chn[2];
17*15da1b50SJoseph Chen ofnode node;
1868ed8338SJoseph Chen
195a54baa7SJoseph Chen uc_key = dev_get_uclass_platdata(dev);
205a54baa7SJoseph Chen if (!uc_key)
215a54baa7SJoseph Chen return -ENXIO;
225a54baa7SJoseph Chen
235a54baa7SJoseph Chen uc_key->type = ADC_KEY;
245a54baa7SJoseph Chen uc_key->name = dev_read_string(dev, "label");
255a54baa7SJoseph Chen ret = dev_read_u32_array(dev_get_parent(dev),
265a54baa7SJoseph Chen "io-channels", chn, ARRAY_SIZE(chn));
275a54baa7SJoseph Chen if (ret) {
285a54baa7SJoseph Chen printf("%s: read 'io-channels' failed, ret=%d\n",
295a54baa7SJoseph Chen uc_key->name, ret);
305a54baa7SJoseph Chen return -EINVAL;
315a54baa7SJoseph Chen }
325a54baa7SJoseph Chen
33*15da1b50SJoseph Chen up_threshold = dev_read_u32_default(dev_get_parent(dev),
345a54baa7SJoseph Chen "keyup-threshold-microvolt", -ENODATA);
35*15da1b50SJoseph Chen if (up_threshold < 0)
36*15da1b50SJoseph Chen return -ENODATA;
3768ed8338SJoseph Chen
385a54baa7SJoseph Chen uc_key->code = dev_read_u32_default(dev, "linux,code", -ENODATA);
39*15da1b50SJoseph Chen if (uc_key->code < 0)
40*15da1b50SJoseph Chen return -ENODATA;
41*15da1b50SJoseph Chen
42*15da1b50SJoseph Chen voltage = dev_read_u32_default(dev, "press-threshold-microvolt", -ENODATA);
43*15da1b50SJoseph Chen if (voltage < 0)
44*15da1b50SJoseph Chen return -ENODATA;
45*15da1b50SJoseph Chen
46*15da1b50SJoseph Chen dev_for_each_subnode(node, dev->parent) {
47*15da1b50SJoseph Chen ret = ofnode_read_s32(node, "press-threshold-microvolt", &t);
48*15da1b50SJoseph Chen if (ret)
49*15da1b50SJoseph Chen return ret;
50*15da1b50SJoseph Chen
51*15da1b50SJoseph Chen if (t > voltage && t < up_threshold)
52*15da1b50SJoseph Chen up_threshold = t;
53*15da1b50SJoseph Chen else if (t < voltage && t > down_threshold)
54*15da1b50SJoseph Chen down_threshold = t;
55*15da1b50SJoseph Chen num++;
5668ed8338SJoseph Chen }
5768ed8338SJoseph Chen
58*15da1b50SJoseph Chen /* although one node only, it doesn't mean only one key on hardware */
59*15da1b50SJoseph Chen if (num == 1) {
60*15da1b50SJoseph Chen down_threshold = voltage - volt_margin;
61*15da1b50SJoseph Chen up_threshold = voltage + volt_margin;
6268ed8338SJoseph Chen }
6364048c53SJoseph Chen
64*15da1b50SJoseph Chen uc_key->in_volt = 1;
655a54baa7SJoseph Chen uc_key->channel = chn[1];
66*15da1b50SJoseph Chen uc_key->center = voltage;
67*15da1b50SJoseph Chen /*
68*15da1b50SJoseph Chen * Define the voltage range such that the button is only pressed
69*15da1b50SJoseph Chen * when the voltage is closest to its own press-threshold-microvolt
70*15da1b50SJoseph Chen */
71*15da1b50SJoseph Chen if (down_threshold < 0)
72*15da1b50SJoseph Chen uc_key->min = 0;
73*15da1b50SJoseph Chen else
74*15da1b50SJoseph Chen uc_key->min = down_threshold + (voltage - down_threshold) / 2;
75*15da1b50SJoseph Chen
76*15da1b50SJoseph Chen uc_key->max = voltage + (up_threshold - voltage) / 2;
7768ed8338SJoseph Chen
7868ed8338SJoseph Chen return 0;
7968ed8338SJoseph Chen }
8068ed8338SJoseph Chen
815a54baa7SJoseph Chen U_BOOT_DRIVER(adc_key) = {
825a54baa7SJoseph Chen .name = "adc_key",
835a54baa7SJoseph Chen .id = UCLASS_KEY,
845a54baa7SJoseph Chen .ofdata_to_platdata = adc_key_ofdata_to_platdata,
8568ed8338SJoseph Chen };
8668ed8338SJoseph Chen
875a54baa7SJoseph Chen /* Key Bus */
adc_key_bus_bind(struct udevice * dev)885a54baa7SJoseph Chen static int adc_key_bus_bind(struct udevice *dev)
895a54baa7SJoseph Chen {
905a54baa7SJoseph Chen return key_bind_children(dev, "adc_key");
915a54baa7SJoseph Chen }
925a54baa7SJoseph Chen
935a54baa7SJoseph Chen static const struct udevice_id adc_key_bus_match[] = {
9468ed8338SJoseph Chen { .compatible = "adc-keys" },
9568ed8338SJoseph Chen { },
9668ed8338SJoseph Chen };
9768ed8338SJoseph Chen
985a54baa7SJoseph Chen U_BOOT_DRIVER(adc_key_bus) = {
995a54baa7SJoseph Chen .name = "adc_key_bus",
1005a54baa7SJoseph Chen .id = UCLASS_SIMPLE_BUS,
1015a54baa7SJoseph Chen .of_match = adc_key_bus_match,
1025a54baa7SJoseph Chen .bind = adc_key_bus_bind,
10368ed8338SJoseph Chen };
104