1b398a9a7SJoseph Chen /* 2b398a9a7SJoseph Chen * (C) Copyright 2017 Rockchip Electronics Co., Ltd 3b398a9a7SJoseph Chen * 4b398a9a7SJoseph Chen * SPDX-License-Identifier: GPL-2.0+ 5b398a9a7SJoseph Chen */ 6b398a9a7SJoseph Chen 7b398a9a7SJoseph Chen #include <dm.h> 8b398a9a7SJoseph Chen #include <key.h> 9*a2df9606SJoseph Chen #include <common.h> 10*a2df9606SJoseph Chen #include <dm.h> 11b398a9a7SJoseph Chen 12*a2df9606SJoseph Chen static inline uint64_t arch_counter_get_cntpct(void) 13*a2df9606SJoseph Chen { 14*a2df9606SJoseph Chen uint64_t cval = 0; 15*a2df9606SJoseph Chen 16*a2df9606SJoseph Chen isb(); 17*a2df9606SJoseph Chen #ifdef CONFIG_ARM64 18*a2df9606SJoseph Chen asm volatile("mrs %0, cntpct_el0" : "=r" (cval)); 19*a2df9606SJoseph Chen #else 20*a2df9606SJoseph Chen asm volatile ("mrrc p15, 0, %Q0, %R0, c14" : "=r" (cval)); 21*a2df9606SJoseph Chen #endif 22*a2df9606SJoseph Chen return cval; 23*a2df9606SJoseph Chen } 24*a2df9606SJoseph Chen 25*a2df9606SJoseph Chen uint64_t key_get_timer(uint64_t base) 26*a2df9606SJoseph Chen { 27*a2df9606SJoseph Chen uint64_t cntpct; 28*a2df9606SJoseph Chen 29*a2df9606SJoseph Chen cntpct = arch_counter_get_cntpct() / 24000UL; 30*a2df9606SJoseph Chen return (cntpct > base) ? (cntpct - base) : 0; 31*a2df9606SJoseph Chen } 32*a2df9606SJoseph Chen 33*a2df9606SJoseph Chen static int key_state_valid(int state) 34*a2df9606SJoseph Chen { 35*a2df9606SJoseph Chen return (state >= KEY_PRESS_NONE && state < KEY_NOT_EXIST); 36*a2df9606SJoseph Chen } 37*a2df9606SJoseph Chen 38*a2df9606SJoseph Chen static int key_read(struct udevice *dev, int code) 39b398a9a7SJoseph Chen { 40b398a9a7SJoseph Chen const struct dm_key_ops *ops = dev_get_driver_ops(dev); 41b398a9a7SJoseph Chen 42b398a9a7SJoseph Chen if (!ops || !ops->read) 43b398a9a7SJoseph Chen return -ENOSYS; 44b398a9a7SJoseph Chen 45*a2df9606SJoseph Chen return ops->read(dev, code); 46b398a9a7SJoseph Chen } 47b398a9a7SJoseph Chen 48*a2df9606SJoseph Chen int platform_key_read(int code) 496e14addfSJoseph Chen { 50*a2df9606SJoseph Chen struct udevice *dev; 51*a2df9606SJoseph Chen int report = KEY_NOT_EXIST; 526e14addfSJoseph Chen 53*a2df9606SJoseph Chen for (uclass_first_device(UCLASS_KEY, &dev); 54*a2df9606SJoseph Chen dev; 55*a2df9606SJoseph Chen uclass_next_device(&dev)) { 56*a2df9606SJoseph Chen debug("key dev.name = %s, code = %d\n", dev->name, code); 57*a2df9606SJoseph Chen report = key_read(dev, code); 58*a2df9606SJoseph Chen if (key_state_valid(report)) { 59*a2df9606SJoseph Chen debug("key dev.name = %s, state=%d\n", dev->name, report); 60*a2df9606SJoseph Chen break; 61*a2df9606SJoseph Chen } 626e14addfSJoseph Chen } 636e14addfSJoseph Chen 64*a2df9606SJoseph Chen return report; 656e14addfSJoseph Chen } 666e14addfSJoseph Chen 67b398a9a7SJoseph Chen UCLASS_DRIVER(key) = { 68b398a9a7SJoseph Chen .id = UCLASS_KEY, 69b398a9a7SJoseph Chen .name = "key", 70b398a9a7SJoseph Chen }; 71