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