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 <adc.h> 9 #include <dm.h> 10 #include <key.h> 11 #include <dm/lists.h> 12 #include <irq-generic.h> 13 14 #define KEY_WARN(fmt, args...) printf("Key Warn: "fmt, ##args) 15 #define KEY_ERR(fmt, args...) printf("Key Error: "fmt, ##args) 16 #define KEY_DBG(fmt, args...) debug("Key Debug: "fmt, ##args) 17 18 static inline uint64_t arch_counter_get_cntpct(void) 19 { 20 uint64_t cval = 0; 21 22 isb(); 23 #ifdef CONFIG_ARM64 24 asm volatile("mrs %0, cntpct_el0" : "=r" (cval)); 25 #else 26 asm volatile("mrrc p15, 0, %Q0, %R0, c14" : "=r" (cval)); 27 #endif 28 return cval; 29 } 30 31 uint64_t key_timer(uint64_t base) 32 { 33 uint64_t cntpct; 34 35 cntpct = arch_counter_get_cntpct() / 24000UL; 36 return (cntpct > base) ? (cntpct - base) : 0; 37 } 38 39 static int key_adc_event(struct dm_key_uclass_platdata *uc_key, int adcval) 40 { 41 return (adcval <= uc_key->max && adcval >= uc_key->min) ? 42 KEY_PRESS_DOWN : KEY_PRESS_NONE; 43 } 44 45 static int key_gpio_event(struct dm_key_uclass_platdata *uc_key) 46 { 47 if (!dm_gpio_is_valid(&uc_key->gpio)) { 48 KEY_ERR("'%s' Invalid gpio\n", uc_key->name); 49 return KEY_PRESS_NONE; 50 } 51 52 return dm_gpio_get_value(&uc_key->gpio) ? 53 KEY_PRESS_DOWN : KEY_PRESS_NONE; 54 } 55 56 static int key_gpio_interrupt_event(struct dm_key_uclass_platdata *uc_key) 57 { 58 int event; 59 60 debug("%s: %s: up=%llu, down=%llu, delta=%llu\n", 61 __func__, uc_key->name, uc_key->rise_ms, uc_key->fall_ms, 62 uc_key->rise_ms - uc_key->fall_ms); 63 64 /* Possible this is machine power-on long pressed, so ignore this */ 65 if (uc_key->fall_ms == 0 && uc_key->rise_ms != 0) { 66 event = KEY_PRESS_NONE; 67 goto out; 68 } 69 70 if ((uc_key->rise_ms > uc_key->fall_ms) && 71 (uc_key->rise_ms - uc_key->fall_ms) >= KEY_LONG_DOWN_MS) { 72 uc_key->rise_ms = 0; 73 uc_key->fall_ms = 0; 74 event = KEY_PRESS_LONG_DOWN; 75 KEY_DBG("%s key long pressed..\n", uc_key->name); 76 } else if (uc_key->fall_ms && 77 key_timer(uc_key->fall_ms) >= KEY_LONG_DOWN_MS) { 78 uc_key->rise_ms = 0; 79 uc_key->fall_ms = 0; 80 event = KEY_PRESS_LONG_DOWN; 81 KEY_DBG("%s key long pressed(hold)..\n", uc_key->name); 82 } else if ((uc_key->rise_ms > uc_key->fall_ms) && 83 (uc_key->rise_ms - uc_key->fall_ms) < KEY_LONG_DOWN_MS) { 84 uc_key->rise_ms = 0; 85 uc_key->fall_ms = 0; 86 event = KEY_PRESS_DOWN; 87 KEY_DBG("%s key short pressed..\n", uc_key->name); 88 /* Possible in charge animation, we enable irq after fuel gauge updated */ 89 } else if (uc_key->rise_ms && uc_key->fall_ms && 90 (uc_key->rise_ms == uc_key->fall_ms)) { 91 uc_key->rise_ms = 0; 92 uc_key->fall_ms = 0; 93 event = KEY_PRESS_DOWN; 94 KEY_DBG("%s key short pressed..\n", uc_key->name); 95 } else { 96 event = KEY_PRESS_NONE; 97 } 98 99 out: 100 return event; 101 } 102 103 int key_is_pressed(int event) 104 { 105 return (event == KEY_PRESS_DOWN || event == KEY_PRESS_LONG_DOWN); 106 } 107 108 static int key_core_read(struct dm_key_uclass_platdata *uc_key) 109 { 110 unsigned int adcval; 111 112 if (uc_key->type == ADC_KEY) { 113 if (adc_channel_single_shot("saradc", 114 uc_key->channel, &adcval)) { 115 KEY_ERR("%s failed to read saradc\n", uc_key->name); 116 return KEY_NOT_EXIST; 117 } 118 119 return key_adc_event(uc_key, adcval); 120 } 121 122 return (uc_key->code == KEY_POWER) ? 123 key_gpio_interrupt_event(uc_key) : 124 key_gpio_event(uc_key); 125 } 126 127 int key_read(int code) 128 { 129 struct dm_key_uclass_platdata *uc_key; 130 struct udevice *dev; 131 struct uclass *uc; 132 bool allow_pre_reloc = false; 133 int ret, event = KEY_NOT_EXIST; 134 135 ret = uclass_get(UCLASS_KEY, &uc); 136 if (ret) 137 return ret; 138 139 try_again: 140 for (uclass_first_device(UCLASS_KEY, &dev); 141 dev; 142 uclass_next_device(&dev)) { 143 uc_key = dev_get_uclass_platdata(dev); 144 145 if (!allow_pre_reloc && uc_key->pre_reloc) 146 continue; 147 148 if (uc_key->code != code) 149 continue; 150 151 event = key_core_read(uc_key); 152 if (key_is_pressed(event)) 153 return event; 154 } 155 156 /* If not find valid key node from kernel, try from u-boot */ 157 if (event == KEY_NOT_EXIST && !allow_pre_reloc) { 158 allow_pre_reloc = true; 159 goto try_again; 160 } 161 162 return event; 163 } 164 165 #if CONFIG_IS_ENABLED(IRQ) 166 #if defined(CONFIG_PWRKEY_DNL_TRIGGER_NUM) && \ 167 (CONFIG_PWRKEY_DNL_TRIGGER_NUM > 0) 168 static void power_key_download(struct dm_key_uclass_platdata *uc_key) 169 { 170 int trig_cnt = CONFIG_PWRKEY_DNL_TRIGGER_NUM; 171 static u64 old_rise_ms; 172 173 if (uc_key->code == KEY_POWER && old_rise_ms != uc_key->rise_ms) { 174 old_rise_ms = uc_key->rise_ms; 175 uc_key->trig_cnt++; 176 if (uc_key->trig_cnt >= trig_cnt) { 177 printf("\nEnter download mode by pwrkey\n"); 178 irq_handler_disable(uc_key->irq); 179 run_command("rockusb 0 $devtype $devnum", 0); 180 run_command("rbrom", 0); 181 } 182 } 183 } 184 185 int pwrkey_download_init(void) 186 { 187 return (KEY_NOT_EXIST == key_read(KEY_POWER)); 188 } 189 #endif 190 191 static void gpio_irq_handler(int irq, void *data) 192 { 193 struct udevice *dev = data; 194 struct dm_key_uclass_platdata *uc_key = dev_get_uclass_platdata(dev); 195 196 if (uc_key->irq != irq) 197 return; 198 199 if (uc_key->irq_thread) { 200 uc_key->irq_thread(irq, data); 201 } else { 202 if (irq_get_gpio_level(irq)) { 203 uc_key->rise_ms = key_timer(0); 204 KEY_DBG("%s: key dn: %llu ms\n", 205 uc_key->name, uc_key->fall_ms); 206 } else { 207 uc_key->fall_ms = key_timer(0); 208 KEY_DBG("%s: key up: %llu ms\n", 209 uc_key->name, uc_key->rise_ms); 210 } 211 212 /* Must delay */ 213 mdelay(10); 214 irq_revert_irq_type(irq); 215 } 216 217 /* Hook event: enter download mode by pwrkey */ 218 #if defined(CONFIG_PWRKEY_DNL_TRIGGER_NUM) && \ 219 (CONFIG_PWRKEY_DNL_TRIGGER_NUM > 0) 220 power_key_download(uc_key); 221 #endif 222 } 223 #endif 224 225 int key_bind_children(struct udevice *dev, const char *drv_name) 226 { 227 const char *name; 228 ofnode node; 229 int ret; 230 231 dev_for_each_subnode(node, dev) { 232 /* 233 * If this node has "compatible" property, this is not 234 * a amp subnode, but a normal device. skip. 235 */ 236 ofnode_get_property(node, "compatible", &ret); 237 if (ret >= 0) 238 continue; 239 240 if (ret != -FDT_ERR_NOTFOUND) 241 return ret; 242 243 name = ofnode_get_name(node); 244 if (!name) 245 return -EINVAL; 246 ret = device_bind_driver_to_node(dev, drv_name, name, 247 node, NULL); 248 if (ret) 249 return ret; 250 } 251 252 return 0; 253 } 254 255 static int key_post_probe(struct udevice *dev) 256 { 257 struct dm_key_uclass_platdata *uc_key; 258 int ret; 259 #ifdef CONFIG_SARADC_ROCKCHIP_V2 260 int margin = 120; 261 #else 262 int margin = 30; 263 #endif 264 uc_key = dev_get_uclass_platdata(dev); 265 if (!uc_key) 266 return -ENXIO; 267 268 /* True from U-Boot key node */ 269 uc_key->pre_reloc = dev_read_bool(dev, "u-boot,dm-pre-reloc") || 270 dev_read_bool(dev, "u-boot,dm-spl"); 271 272 if (uc_key->type == ADC_KEY) { 273 uc_key->max = uc_key->adcval + margin; 274 uc_key->min = uc_key->adcval > margin ? 275 uc_key->adcval - margin : 0; 276 } else { 277 if (uc_key->code == KEY_POWER) { 278 #if CONFIG_IS_ENABLED(IRQ) 279 int irq; 280 281 if (uc_key->skip_irq_init) 282 return 0; 283 284 irq = phandle_gpio_to_irq(uc_key->gpios[0], 285 uc_key->gpios[1]); 286 if (irq < 0) { 287 KEY_ERR("%s: failed to request irq, ret=%d\n", 288 uc_key->name, irq); 289 return irq; 290 } 291 292 if (uc_key->code != KEY_POWER && uc_key->irq_thread) { 293 KEY_WARN("%s: only power key can request irq thread\n", 294 uc_key->name); 295 return -EINVAL; 296 } 297 298 uc_key->irq = irq; 299 irq_install_handler(irq, gpio_irq_handler, dev); 300 irq_set_irq_type(irq, IRQ_TYPE_EDGE_FALLING); 301 irq_handler_enable(irq); 302 #else 303 KEY_WARN("%s: no IRQ framework available\n", uc_key->name); 304 #endif 305 } else { 306 ret = gpio_request_by_name(dev, "gpios", 0, 307 &uc_key->gpio, GPIOD_IS_IN); 308 if (ret) { 309 KEY_ERR("%s: failed to request gpio, ret=%d\n", 310 uc_key->name, ret); 311 return ret; 312 } 313 } 314 } 315 316 #ifdef DEBUG 317 printf("[%s] (%s, %s, %s):\n", uc_key->name, 318 uc_key->type == ADC_KEY ? "ADC" : "GPIO", 319 uc_key->pre_reloc ? "U-Boot" : "Kernel", 320 dev->parent->name); 321 322 if (uc_key->type == ADC_KEY) { 323 printf(" adcval: %d (%d, %d)\n", uc_key->adcval, 324 uc_key->min, uc_key->max); 325 printf(" channel: %d\n\n", uc_key->channel); 326 } else { 327 const char *gpio_name = 328 ofnode_get_name(ofnode_get_by_phandle(uc_key->gpios[0])); 329 330 printf(" irq: %d\n", uc_key->irq); 331 printf(" gpio[0]: %s\n", gpio_name); 332 printf(" gpio[1]: %d\n\n", uc_key->gpios[1]); 333 } 334 #endif 335 336 return 0; 337 } 338 339 UCLASS_DRIVER(key) = { 340 .id = UCLASS_KEY, 341 .name = "key", 342 .post_probe = key_post_probe, 343 .per_device_platdata_auto_alloc_size = 344 sizeof(struct dm_key_uclass_platdata), 345 }; 346