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 <adc.h> 9 #include <common.h> 10 #include <console.h> 11 #include <dm.h> 12 #include <errno.h> 13 #include <fdtdec.h> 14 #include <malloc.h> 15 #include <key.h> 16 #include <linux/input.h> 17 #include <errno.h> 18 #include <dm/read.h> 19 #include <irq-generic.h> 20 #include <irq-platform.h> 21 22 #define ADC_MARGIN 30 23 #define MAX_KEY_NR 10 24 25 struct rk_key_priv { 26 u32 key_nr; 27 }; 28 29 enum { 30 INVAL_KEY = 0, 31 ADC_KEY, 32 GPIO_KEY, 33 }; 34 35 static void gpio_irq_handler(int irq, void *data) 36 { 37 struct udevice *dev = data; 38 struct rk_key_priv *priv = dev_get_priv(dev); 39 struct input_key *key = dev_get_platdata(dev); 40 int i; 41 42 for (i = 0; i < priv->key_nr; i++) { 43 if (key[i].irq != irq) 44 continue; 45 46 /* up event */ 47 if (irq_get_gpio_level(irq)) { 48 key[i].up_t = key_get_timer(0); 49 debug("%s: key down: %llu ms\n", 50 key[i].name, key[i].down_t); 51 /* down event */ 52 } else { 53 key[i].down_t = key_get_timer(0); 54 debug("%s: key up: %llu ms\n", 55 key[i].name, key[i].up_t); 56 } 57 /* Must delay */ 58 mdelay(10); 59 irq_revert_irq_type(irq); 60 } 61 } 62 63 static int rk_keys_ofdata_to_platdata(struct udevice *dev) 64 { 65 struct rk_key_priv *priv = dev_get_priv(dev); 66 struct input_key *key = dev_get_platdata(dev); 67 u32 adc_channels[2], gpios[2], adcval, i = 0; 68 ofnode node; 69 int irq; 70 71 /* Get IO channel */ 72 if (dev_read_u32_array(dev, "io-channels", adc_channels, 2)) { 73 printf("%s: failed to read 'io-channels'\n", __func__); 74 return -EINVAL; 75 } 76 77 dev_for_each_subnode(node, dev) { 78 /* This is an ACD key */ 79 if (!ofnode_read_u32(node, "rockchip,adc_value", &adcval)) { 80 key[i].name = ofnode_read_string(node, "label"); 81 key[i].flag = ADC_KEY; 82 key[i].margin = ADC_MARGIN; 83 key[i].value = adcval; 84 key[i].channel = adc_channels[1]; 85 if (ofnode_read_u32(node, "linux,code", &key[i].code)) { 86 printf("%s: failed to read 'linux,code'\n", 87 key[i].name); 88 return -EINVAL; 89 } 90 /* This is a GPIO key */ 91 } else { 92 key[i].name = ofnode_read_string(node, "label"); 93 key[i].flag = GPIO_KEY; 94 if (ofnode_read_u32_array(node, "gpios", gpios, 2)) { 95 printf("%s: failed to read 'gpios'\n", 96 key[i].name); 97 return -EINVAL; 98 } 99 if (ofnode_read_u32(node, "linux,code", &key[i].code)) { 100 printf("%s: failed read 'linux,code'\n", 101 key[i].name); 102 return -EINVAL; 103 } 104 105 /* Request irq */ 106 irq = phandle_gpio_to_irq(gpios[0], gpios[1]); 107 if (irq < 0) { 108 printf("%s: failed to request irq, ret=%d\n", 109 __func__, irq); 110 return irq; 111 } 112 key[i].irq = irq; 113 irq_install_handler(irq, gpio_irq_handler, dev); 114 irq_handler_enable(irq); 115 irq_set_irq_type(irq, IRQ_TYPE_EDGE_FALLING); 116 } 117 118 debug("%s: name=%s: code=%d, val=%d, channel=%d, flag=%d, margin=%d\n", 119 __func__, key[i].name, key[i].code, key[i].value, 120 key[i].channel, key[i].flag, key[i].margin); 121 122 /* Next node */ 123 i++; 124 priv->key_nr = i; 125 if (i >= MAX_KEY_NR) { 126 printf("Too many keys, Max support: %d\n", MAX_KEY_NR); 127 return -EINVAL; 128 } 129 } 130 131 return 0; 132 } 133 134 static int rk_keys_read(struct udevice *dev, int code) 135 { 136 struct rk_key_priv *priv = dev_get_priv(dev); 137 struct input_key *key = dev_get_platdata(dev); 138 int report = KEY_NOT_EXIST; 139 int max, min, i = 0; 140 unsigned int adcval; 141 142 for (i = 0; i < priv->key_nr; i++) { 143 if (key[i].code != code) 144 continue; 145 146 if (key[i].flag == ADC_KEY) { 147 if (adc_channel_single_shot("saradc", 148 key[i].channel, &adcval)) { 149 printf("%s: failed to read saradc\n", 150 key[i].name); 151 } else { 152 report = key_parse_adc_event(key[i], adcval); 153 } 154 } else { 155 report = key_parse_gpio_event(key[i]); 156 } 157 break; 158 } 159 160 return report; 161 } 162 163 static const struct dm_key_ops key_ops = { 164 .name = "rk-keys", 165 .read = rk_keys_read, 166 }; 167 168 static const struct udevice_id rk_keys_ids[] = { 169 { .compatible = "rockchip,key" }, 170 { }, 171 }; 172 173 U_BOOT_DRIVER(rk_keys) = { 174 .name = "rk-keys", 175 .id = UCLASS_KEY, 176 .ops = &key_ops, 177 .of_match = rk_keys_ids, 178 .ofdata_to_platdata = rk_keys_ofdata_to_platdata, 179 .platdata_auto_alloc_size = sizeof(struct input_key) * MAX_KEY_NR, 180 .priv_auto_alloc_size = sizeof(struct rk_key_priv), 181 }; 182