1 /* 2 * (C) Copyright 2017 Rockchip Electronics Co., Ltd 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <common.h> 8 #include <dm.h> 9 #include <key.h> 10 11 static int adc_key_ofdata_to_platdata(struct udevice *dev) 12 { 13 struct dm_key_uclass_platdata *uc_key; 14 int t, down_threshold = -1, up_threshold; 15 int ret, num = 0, volt_margin = 150000; /* will be div 2 */ 16 u32 voltage, chn[2]; 17 ofnode node; 18 19 uc_key = dev_get_uclass_platdata(dev); 20 if (!uc_key) 21 return -ENXIO; 22 23 uc_key->type = ADC_KEY; 24 uc_key->name = dev_read_string(dev, "label"); 25 ret = dev_read_u32_array(dev_get_parent(dev), 26 "io-channels", chn, ARRAY_SIZE(chn)); 27 if (ret) { 28 printf("%s: read 'io-channels' failed, ret=%d\n", 29 uc_key->name, ret); 30 return -EINVAL; 31 } 32 33 up_threshold = dev_read_u32_default(dev_get_parent(dev), 34 "keyup-threshold-microvolt", -ENODATA); 35 if (up_threshold < 0) 36 return -ENODATA; 37 38 uc_key->code = dev_read_u32_default(dev, "linux,code", -ENODATA); 39 if (uc_key->code < 0) 40 return -ENODATA; 41 42 voltage = dev_read_u32_default(dev, "press-threshold-microvolt", -ENODATA); 43 if (voltage < 0) 44 return -ENODATA; 45 46 dev_for_each_subnode(node, dev->parent) { 47 ret = ofnode_read_s32(node, "press-threshold-microvolt", &t); 48 if (ret) 49 return ret; 50 51 if (t > voltage && t < up_threshold) 52 up_threshold = t; 53 else if (t < voltage && t > down_threshold) 54 down_threshold = t; 55 num++; 56 } 57 58 /* although one node only, it doesn't mean only one key on hardware */ 59 if (num == 1) { 60 down_threshold = voltage - volt_margin; 61 up_threshold = voltage + volt_margin; 62 } 63 64 uc_key->in_volt = 1; 65 uc_key->channel = chn[1]; 66 uc_key->center = voltage; 67 /* 68 * Define the voltage range such that the button is only pressed 69 * when the voltage is closest to its own press-threshold-microvolt 70 */ 71 if (down_threshold < 0) 72 uc_key->min = 0; 73 else 74 uc_key->min = down_threshold + (voltage - down_threshold) / 2; 75 76 uc_key->max = voltage + (up_threshold - voltage) / 2; 77 78 return 0; 79 } 80 81 U_BOOT_DRIVER(adc_key) = { 82 .name = "adc_key", 83 .id = UCLASS_KEY, 84 .ofdata_to_platdata = adc_key_ofdata_to_platdata, 85 }; 86 87 /* Key Bus */ 88 static int adc_key_bus_bind(struct udevice *dev) 89 { 90 return key_bind_children(dev, "adc_key"); 91 } 92 93 static const struct udevice_id adc_key_bus_match[] = { 94 { .compatible = "adc-keys" }, 95 { }, 96 }; 97 98 U_BOOT_DRIVER(adc_key_bus) = { 99 .name = "adc_key_bus", 100 .id = UCLASS_SIMPLE_BUS, 101 .of_match = adc_key_bus_match, 102 .bind = adc_key_bus_bind, 103 }; 104