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 MAX_KEY_NR 10 23 24 struct gpio_key_priv { 25 u32 key_nr; 26 }; 27 28 static void gpio_irq_handler(int irq, void *data) 29 { 30 struct udevice *dev = data; 31 struct gpio_key_priv *priv = dev_get_priv(dev); 32 struct input_key *key = dev_get_platdata(dev); 33 int i; 34 35 for (i = 0; i < priv->key_nr; i++) { 36 if (key[i].irq != irq) 37 continue; 38 39 /* up event */ 40 if (irq_get_gpio_level(irq)) { 41 key[i].up_t = key_get_timer(0); 42 debug("%s: key down: %llu ms\n", 43 key[i].name, key[i].down_t); 44 /* down event */ 45 } else { 46 key[i].down_t = key_get_timer(0); 47 debug("%s: key up: %llu ms\n", 48 key[i].name, key[i].up_t); 49 } 50 /* Must delay */ 51 mdelay(10); 52 irq_revert_irq_type(irq); 53 } 54 } 55 56 static int gpio_key_ofdata_to_platdata(struct udevice *dev) 57 { 58 struct gpio_key_priv *priv = dev_get_priv(dev); 59 struct input_key *key = dev_get_platdata(dev); 60 u32 gpios[2], i = 0; 61 ofnode node; 62 int irq; 63 64 dev_for_each_subnode(node, dev) { 65 key[i].name = ofnode_read_string(node, "label"); 66 if (ofnode_read_u32(node, "linux,code", &key[i].code)) { 67 printf("failed read 'linux,code' of %s key\n", 68 key[i].name); 69 return -EINVAL; 70 } 71 if (ofnode_read_u32_array(node, "gpios", gpios, 2)) { 72 printf("failed to read 'gpios' of %s key\n", 73 key[i].name); 74 return -EINVAL; 75 } 76 77 /* Must register as interrupt, be able to wakeup system */ 78 irq = phandle_gpio_to_irq(gpios[0], gpios[1]); 79 if (irq < 0) { 80 printf("failed to request irq for gpio, ret=%d\n", irq); 81 return irq; 82 } 83 key[i].irq = irq; 84 irq_install_handler(irq, gpio_irq_handler, dev); 85 irq_handler_enable(irq); 86 irq_set_irq_type(irq, IRQ_TYPE_EDGE_FALLING); 87 88 debug("%s: name=%s: code=%d\n", 89 __func__, key[i].name, key[i].code); 90 91 /* Next node */ 92 i++; 93 priv->key_nr = i; 94 if (i >= MAX_KEY_NR) { 95 printf("Too many keys, Max support: %d\n", MAX_KEY_NR); 96 return -EINVAL; 97 } 98 } 99 100 return 0; 101 } 102 103 static int gpio_key_read(struct udevice *dev, int code) 104 { 105 struct gpio_key_priv *priv = dev_get_priv(dev); 106 struct input_key *key = dev_get_platdata(dev); 107 u32 report = KEY_NOT_EXIST; 108 int i = 0; 109 110 for (i = 0; i < priv->key_nr; i++) { 111 if (key[i].code != code) 112 continue; 113 114 debug("%s: long key ms: %llu, up=%llu, down=%llu\n", 115 key[i].name, key[i].up_t - key[i].down_t, 116 key[i].up_t, key[i].down_t); 117 118 if (key[i].down_t && (key[i].up_t > key[i].down_t) && 119 (key[i].up_t - key[i].down_t) >= KEY_LONG_DOWN_MS) { 120 key[i].up_t = 0; 121 key[i].down_t = 0; 122 report = KEY_PRESS_LONG_DOWN; 123 printf("'%s' key long pressed down\n", key[i].name); 124 } else if (key[i].down_t && key_get_timer(key[i].down_t) >= 125 KEY_LONG_DOWN_MS) { 126 key[i].up_t = 0; 127 key[i].down_t = 0; 128 report = KEY_PRESS_LONG_DOWN; 129 printf("'%s' key long pressed down(hold)\n", 130 key[i].name); 131 } else if ((key[i].up_t > key[i].down_t) && 132 (key[i].up_t - key[i].down_t) < KEY_LONG_DOWN_MS) { 133 key[i].up_t = 0; 134 key[i].down_t = 0; 135 report = KEY_PRESS_DOWN; 136 printf("'%s' key pressed down\n", key[i].name); 137 } else { 138 report = KEY_PRESS_NONE; 139 } 140 } 141 142 return report; 143 } 144 145 static const struct dm_key_ops key_ops = { 146 .name = "gpio-keys", 147 .read = gpio_key_read, 148 }; 149 150 static const struct udevice_id gpio_key_ids[] = { 151 { .compatible = "gpio-keys" }, 152 { }, 153 }; 154 155 U_BOOT_DRIVER(gpio_keys) = { 156 .name = "gpio-keys", 157 .id = UCLASS_KEY, 158 .of_match = gpio_key_ids, 159 .ops = &key_ops, 160 .ofdata_to_platdata = gpio_key_ofdata_to_platdata, 161 .platdata_auto_alloc_size = sizeof(struct input_key) * MAX_KEY_NR, 162 .priv_auto_alloc_size = sizeof(struct gpio_key_priv), 163 }; 164