1 /* 2 * (C) Copyright 2017 Rockchip Electronics Co., Ltd 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <dm.h> 8 #include <dm/read.h> 9 #include <adc.h> 10 #include <common.h> 11 #include <console.h> 12 #include <errno.h> 13 #include <fdtdec.h> 14 #include <malloc.h> 15 #include <key.h> 16 #include <linux/input.h> 17 18 #define ADC_MARGIN 30 19 #define MAX_KEY_NR 10 20 21 struct adc_key_priv { 22 u32 key_nr; 23 }; 24 25 static int adc_keys_ofdata_to_platdata(struct udevice *dev) 26 { 27 struct adc_key_priv *priv = dev_get_priv(dev); 28 struct input_key *key = dev_get_platdata(dev); 29 u32 adc_channels[2], i = 0, microvolt; 30 int vref, err; 31 ofnode node; 32 33 /* Get vref */ 34 vref = dev_read_u32_default(dev, "keyup-threshold-microvolt", -1); 35 if (vref < 0) { 36 printf("failed to read 'keyup-threshold-microvolt', ret=%d\n", 37 vref); 38 return -EINVAL; 39 } 40 41 /* Get IO channel */ 42 err = dev_read_u32_array(dev, "io-channels", adc_channels, 2); 43 if (err) { 44 printf("failed to read 'io-channels' of %s key, ret=%d\n", 45 key->name, err); 46 return -EINVAL; 47 } 48 49 /* Parse every adc key data */ 50 dev_for_each_subnode(node, dev) { 51 key[i].name = ofnode_read_string(node, "label"); 52 key[i].vref = vref; 53 key[i].margin = ADC_MARGIN; 54 key[i].channel = adc_channels[1]; 55 if (ofnode_read_u32(node, "linux,code", &key[i].code)) { 56 printf("%s: failed to read 'linux,code', ret=%d\n", 57 key[i].name, key[i].code); 58 return -EINVAL; 59 } 60 if (ofnode_read_u32(node, "press-threshold-microvolt", 61 µvolt)) { 62 printf("%s: failed read 'press-threshold-microvolt', ret=%d\n", 63 key[i].name, microvolt); 64 return -EINVAL; 65 } 66 /* Convert microvolt to adc value */ 67 key[i].value = microvolt / (key[i].vref / 1024); 68 69 debug("%s: name=%s: code=%d, vref=%d, margin=%d, channel=%d, val=%d\n", 70 __func__, key[i].name, key[i].code, key[i].vref, 71 key[i].margin, key[i].channel, key[i].value); 72 73 /* Next node */ 74 i++; 75 priv->key_nr = i; 76 if (i >= MAX_KEY_NR) { 77 printf("Too many keys, Max support: %d\n", MAX_KEY_NR); 78 return -EINVAL; 79 } 80 } 81 82 return 0; 83 } 84 85 static int adc_keys_read(struct udevice *dev, int code) 86 { 87 struct adc_key_priv *priv = dev_get_priv(dev); 88 struct input_key *key = dev_get_platdata(dev); 89 int report = KEY_NOT_EXIST; 90 int max, min, i = 0; 91 unsigned int adcval; 92 93 for (i = 0; i < priv->key_nr; i++) { 94 if (key[i].code != code) 95 continue; 96 97 if (adc_channel_single_shot("saradc", 98 key[i].channel, &adcval)) { 99 printf("%s: failed to read saradc\n", key[i].name); 100 } else { 101 /* Get min, max */ 102 max = key[i].value + key[i].margin; 103 if (key[i].value > key[i].margin) 104 min = key[i].value - key[i].margin; 105 else 106 min = key[i].value; 107 108 /* Check */ 109 if ((adcval <= max) && (adcval >= min)) { 110 report = KEY_PRESS_DOWN; 111 printf("'%s' key pressed down\n", 112 key[i].name); 113 } else { 114 report = KEY_PRESS_NONE; 115 } 116 } 117 break; 118 } 119 120 return report; 121 } 122 123 static const struct dm_key_ops key_ops = { 124 .name = "adc_keys", 125 .read = adc_keys_read, 126 }; 127 128 static const struct udevice_id adc_keys_ids[] = { 129 { .compatible = "adc-keys" }, 130 { }, 131 }; 132 133 U_BOOT_DRIVER(adc_keys) = { 134 .name = "adc-keys", 135 .id = UCLASS_KEY, 136 .ops = &key_ops, 137 .of_match = adc_keys_ids, 138 .ofdata_to_platdata = adc_keys_ofdata_to_platdata, 139 .platdata_auto_alloc_size = sizeof(struct input_key) * MAX_KEY_NR, 140 .priv_auto_alloc_size = sizeof(struct adc_key_priv), 141 }; 142