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