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 764048c53SJoseph Chen #include <common.h> 864048c53SJoseph Chen #include <adc.h> 915da1b50SJoseph Chen #include <div64.h> 10b398a9a7SJoseph Chen #include <dm.h> 1118fdcbceSJoseph Chen #include <irq-generic.h> 12b398a9a7SJoseph Chen #include <key.h> 135a54baa7SJoseph Chen #include <dm/lists.h> 1418fdcbceSJoseph Chen #include <dm/uclass-internal.h> 1564048c53SJoseph Chen 165a54baa7SJoseph Chen #define KEY_WARN(fmt, args...) printf("Key Warn: "fmt, ##args) 175a54baa7SJoseph Chen #define KEY_ERR(fmt, args...) printf("Key Error: "fmt, ##args) 185a54baa7SJoseph Chen #define KEY_DBG(fmt, args...) debug("Key Debug: "fmt, ##args) 19adba3792SJoseph Chen 20a2df9606SJoseph Chen static inline uint64_t arch_counter_get_cntpct(void) 21a2df9606SJoseph Chen { 22a2df9606SJoseph Chen uint64_t cval = 0; 23a2df9606SJoseph Chen 24a2df9606SJoseph Chen isb(); 25a2df9606SJoseph Chen #ifdef CONFIG_ARM64 26a2df9606SJoseph Chen asm volatile("mrs %0, cntpct_el0" : "=r" (cval)); 27a2df9606SJoseph Chen #else 28a2df9606SJoseph Chen asm volatile("mrrc p15, 0, %Q0, %R0, c14" : "=r" (cval)); 29a2df9606SJoseph Chen #endif 30a2df9606SJoseph Chen return cval; 31a2df9606SJoseph Chen } 32a2df9606SJoseph Chen 3364048c53SJoseph Chen uint64_t key_timer(uint64_t base) 34a2df9606SJoseph Chen { 35a2df9606SJoseph Chen uint64_t cntpct; 36a2df9606SJoseph Chen 37a2df9606SJoseph Chen cntpct = arch_counter_get_cntpct() / 24000UL; 38a2df9606SJoseph Chen return (cntpct > base) ? (cntpct - base) : 0; 39a2df9606SJoseph Chen } 40a2df9606SJoseph Chen 41eb104afcSJoseph Chen #ifdef CONFIG_ADC 429b0d00c5SJoseph Chen static int adc_raw_to_mV(struct udevice *dev, unsigned int raw, int *mV) 43a2df9606SJoseph Chen { 4415da1b50SJoseph Chen unsigned int data_mask; 4515da1b50SJoseph Chen int ret, vref = 1800000; 4615da1b50SJoseph Chen u64 raw64 = raw; 4715da1b50SJoseph Chen 4815da1b50SJoseph Chen ret = adc_data_mask(dev, &data_mask); 4915da1b50SJoseph Chen if (ret) 5015da1b50SJoseph Chen return ret; 5115da1b50SJoseph Chen 5215da1b50SJoseph Chen raw64 *= vref; 5315da1b50SJoseph Chen do_div(raw64, data_mask); 549b0d00c5SJoseph Chen *mV = raw64; 5515da1b50SJoseph Chen 5615da1b50SJoseph Chen return 0; 5715da1b50SJoseph Chen } 5815da1b50SJoseph Chen 5915da1b50SJoseph Chen static int key_adc_event(struct udevice *dev, 6015da1b50SJoseph Chen struct dm_key_uclass_platdata *uc_key, int adcval) 6115da1b50SJoseph Chen { 6215da1b50SJoseph Chen int val = adcval; 6315da1b50SJoseph Chen 6415da1b50SJoseph Chen if (uc_key->in_volt) { 659b0d00c5SJoseph Chen if (adc_raw_to_mV(dev, adcval, &val)) 6615da1b50SJoseph Chen return KEY_PRESS_NONE; 6715da1b50SJoseph Chen } 6815da1b50SJoseph Chen 699b0d00c5SJoseph Chen debug("[%s] <%d, %d, %d>: adcval=%d -> mV=%d\n", 7015da1b50SJoseph Chen uc_key->name, uc_key->min, uc_key->center, uc_key->max, 7115da1b50SJoseph Chen adcval, val); 7215da1b50SJoseph Chen 7315da1b50SJoseph Chen return (val <= uc_key->max && val >= uc_key->min) ? 745a54baa7SJoseph Chen KEY_PRESS_DOWN : KEY_PRESS_NONE; 753fb84000SJoseph Chen } 76eb104afcSJoseph Chen #endif 773fb84000SJoseph Chen 785a54baa7SJoseph Chen static int key_gpio_event(struct dm_key_uclass_platdata *uc_key) 793fb84000SJoseph Chen { 805a54baa7SJoseph Chen if (!dm_gpio_is_valid(&uc_key->gpio)) { 815a54baa7SJoseph Chen KEY_ERR("'%s' Invalid gpio\n", uc_key->name); 8264048c53SJoseph Chen return KEY_PRESS_NONE; 8364048c53SJoseph Chen } 8464048c53SJoseph Chen 855a54baa7SJoseph Chen return dm_gpio_get_value(&uc_key->gpio) ? 865a54baa7SJoseph Chen KEY_PRESS_DOWN : KEY_PRESS_NONE; 8764048c53SJoseph Chen } 8864048c53SJoseph Chen 895a54baa7SJoseph Chen static int key_gpio_interrupt_event(struct dm_key_uclass_platdata *uc_key) 9064048c53SJoseph Chen { 915a54baa7SJoseph Chen int event; 923fb84000SJoseph Chen 933fb84000SJoseph Chen debug("%s: %s: up=%llu, down=%llu, delta=%llu\n", 945a54baa7SJoseph Chen __func__, uc_key->name, uc_key->rise_ms, uc_key->fall_ms, 955a54baa7SJoseph Chen uc_key->rise_ms - uc_key->fall_ms); 963fb84000SJoseph Chen 973fb84000SJoseph Chen /* Possible this is machine power-on long pressed, so ignore this */ 985a54baa7SJoseph Chen if (uc_key->fall_ms == 0 && uc_key->rise_ms != 0) { 995a54baa7SJoseph Chen event = KEY_PRESS_NONE; 1003fb84000SJoseph Chen goto out; 1013fb84000SJoseph Chen } 1023fb84000SJoseph Chen 1035a54baa7SJoseph Chen if ((uc_key->rise_ms > uc_key->fall_ms) && 1045a54baa7SJoseph Chen (uc_key->rise_ms - uc_key->fall_ms) >= KEY_LONG_DOWN_MS) { 1055a54baa7SJoseph Chen uc_key->rise_ms = 0; 1065a54baa7SJoseph Chen uc_key->fall_ms = 0; 1075a54baa7SJoseph Chen event = KEY_PRESS_LONG_DOWN; 1085a54baa7SJoseph Chen KEY_DBG("%s key long pressed..\n", uc_key->name); 1095a54baa7SJoseph Chen } else if (uc_key->fall_ms && 1105a54baa7SJoseph Chen key_timer(uc_key->fall_ms) >= KEY_LONG_DOWN_MS) { 1115a54baa7SJoseph Chen uc_key->rise_ms = 0; 1125a54baa7SJoseph Chen uc_key->fall_ms = 0; 1135a54baa7SJoseph Chen event = KEY_PRESS_LONG_DOWN; 1145a54baa7SJoseph Chen KEY_DBG("%s key long pressed(hold)..\n", uc_key->name); 1155a54baa7SJoseph Chen } else if ((uc_key->rise_ms > uc_key->fall_ms) && 1165a54baa7SJoseph Chen (uc_key->rise_ms - uc_key->fall_ms) < KEY_LONG_DOWN_MS) { 1175a54baa7SJoseph Chen uc_key->rise_ms = 0; 1185a54baa7SJoseph Chen uc_key->fall_ms = 0; 1195a54baa7SJoseph Chen event = KEY_PRESS_DOWN; 1205a54baa7SJoseph Chen KEY_DBG("%s key short pressed..\n", uc_key->name); 12164048c53SJoseph Chen /* Possible in charge animation, we enable irq after fuel gauge updated */ 1225a54baa7SJoseph Chen } else if (uc_key->rise_ms && uc_key->fall_ms && 1235a54baa7SJoseph Chen (uc_key->rise_ms == uc_key->fall_ms)) { 1245a54baa7SJoseph Chen uc_key->rise_ms = 0; 1255a54baa7SJoseph Chen uc_key->fall_ms = 0; 1265a54baa7SJoseph Chen event = KEY_PRESS_DOWN; 1275a54baa7SJoseph Chen KEY_DBG("%s key short pressed..\n", uc_key->name); 1283fb84000SJoseph Chen } else { 1295a54baa7SJoseph Chen event = KEY_PRESS_NONE; 1303fb84000SJoseph Chen } 1313fb84000SJoseph Chen 1323fb84000SJoseph Chen out: 1335a54baa7SJoseph Chen return event; 13464048c53SJoseph Chen } 13564048c53SJoseph Chen 1365a54baa7SJoseph Chen int key_is_pressed(int event) 13764048c53SJoseph Chen { 1385a54baa7SJoseph Chen return (event == KEY_PRESS_DOWN || event == KEY_PRESS_LONG_DOWN); 13964048c53SJoseph Chen } 14064048c53SJoseph Chen 1415a54baa7SJoseph Chen static int key_core_read(struct dm_key_uclass_platdata *uc_key) 14264048c53SJoseph Chen { 143eb104afcSJoseph Chen if (uc_key->type == ADC_KEY) { 144eb104afcSJoseph Chen #ifdef CONFIG_ADC 14515da1b50SJoseph Chen struct udevice *dev; 14664048c53SJoseph Chen unsigned int adcval; 14715da1b50SJoseph Chen int ret; 14864048c53SJoseph Chen 14915da1b50SJoseph Chen ret = uclass_get_device_by_name(UCLASS_ADC, "saradc", &dev); 150*a6c9ff86SJoseph Chen if (ret) 151*a6c9ff86SJoseph Chen ret = uclass_get_device_by_name(UCLASS_ADC, "adc", &dev); 15215da1b50SJoseph Chen if (ret) { 15315da1b50SJoseph Chen KEY_ERR("%s: No saradc\n", uc_key->name); 1545a54baa7SJoseph Chen return KEY_NOT_EXIST; 15564048c53SJoseph Chen } 15664048c53SJoseph Chen 15715da1b50SJoseph Chen ret = adc_start_channel(dev, uc_key->channel); 15815da1b50SJoseph Chen if (ret) { 15915da1b50SJoseph Chen KEY_ERR("%s: Failed to start saradc\n", uc_key->name); 16015da1b50SJoseph Chen return KEY_NOT_EXIST; 16115da1b50SJoseph Chen } 16215da1b50SJoseph Chen 16315da1b50SJoseph Chen ret = adc_channel_data(dev, uc_key->channel, &adcval); 16415da1b50SJoseph Chen if (ret) { 16515da1b50SJoseph Chen KEY_ERR("%s: Failed to read saradc, %d\n", uc_key->name, ret); 16615da1b50SJoseph Chen return KEY_NOT_EXIST; 16715da1b50SJoseph Chen } 16815da1b50SJoseph Chen 16915da1b50SJoseph Chen return key_adc_event(dev, uc_key, adcval); 170eb104afcSJoseph Chen #else 171eb104afcSJoseph Chen return KEY_NOT_EXIST; 172eb104afcSJoseph Chen #endif 1735a54baa7SJoseph Chen } 17464048c53SJoseph Chen 1755a54baa7SJoseph Chen return (uc_key->code == KEY_POWER) ? 1765a54baa7SJoseph Chen key_gpio_interrupt_event(uc_key) : 1775a54baa7SJoseph Chen key_gpio_event(uc_key); 1789f1dd9dfSJoseph Chen } 1799f1dd9dfSJoseph Chen 1809f1dd9dfSJoseph Chen int key_read(int code) 1819f1dd9dfSJoseph Chen { 1825a54baa7SJoseph Chen struct dm_key_uclass_platdata *uc_key; 1839f1dd9dfSJoseph Chen struct udevice *dev; 1845a54baa7SJoseph Chen struct uclass *uc; 1855a54baa7SJoseph Chen bool allow_pre_reloc = false; 1865a54baa7SJoseph Chen int ret, event = KEY_NOT_EXIST; 1879f1dd9dfSJoseph Chen 1885a54baa7SJoseph Chen ret = uclass_get(UCLASS_KEY, &uc); 1895a54baa7SJoseph Chen if (ret) 1905a54baa7SJoseph Chen return ret; 1915a54baa7SJoseph Chen 1925a54baa7SJoseph Chen try_again: 1939f1dd9dfSJoseph Chen for (uclass_first_device(UCLASS_KEY, &dev); 1949f1dd9dfSJoseph Chen dev; 1959f1dd9dfSJoseph Chen uclass_next_device(&dev)) { 1965a54baa7SJoseph Chen uc_key = dev_get_uclass_platdata(dev); 1979f1dd9dfSJoseph Chen 1985a54baa7SJoseph Chen if (!allow_pre_reloc && uc_key->pre_reloc) 1999f1dd9dfSJoseph Chen continue; 2009f1dd9dfSJoseph Chen 2015a54baa7SJoseph Chen if (uc_key->code != code) 2029f1dd9dfSJoseph Chen continue; 2039f1dd9dfSJoseph Chen 2045a54baa7SJoseph Chen event = key_core_read(uc_key); 2055a54baa7SJoseph Chen if (key_is_pressed(event)) 2065a54baa7SJoseph Chen return event; 2075a54baa7SJoseph Chen } 2085a54baa7SJoseph Chen 2095a54baa7SJoseph Chen /* If not find valid key node from kernel, try from u-boot */ 2105a54baa7SJoseph Chen if (event == KEY_NOT_EXIST && !allow_pre_reloc) { 2115a54baa7SJoseph Chen allow_pre_reloc = true; 2125a54baa7SJoseph Chen goto try_again; 2135a54baa7SJoseph Chen } 2145a54baa7SJoseph Chen 2155a54baa7SJoseph Chen return event; 2165a54baa7SJoseph Chen } 2175a54baa7SJoseph Chen 21818fdcbceSJoseph Chen int key_exist(int code) 21918fdcbceSJoseph Chen { 22018fdcbceSJoseph Chen struct dm_key_uclass_platdata *uc_key; 22118fdcbceSJoseph Chen struct udevice *dev; 22218fdcbceSJoseph Chen 22318fdcbceSJoseph Chen for (uclass_find_first_device(UCLASS_KEY, &dev); 22418fdcbceSJoseph Chen dev; 22518fdcbceSJoseph Chen uclass_find_next_device(&dev)) { 22618fdcbceSJoseph Chen uc_key = dev_get_uclass_platdata(dev); 22718fdcbceSJoseph Chen 22818fdcbceSJoseph Chen if (uc_key->code == code) 22918fdcbceSJoseph Chen return 1; 23018fdcbceSJoseph Chen } 23118fdcbceSJoseph Chen 23218fdcbceSJoseph Chen return 0; 23318fdcbceSJoseph Chen } 23418fdcbceSJoseph Chen 2357cef7918SJoseph Chen #if CONFIG_IS_ENABLED(IRQ) 2361a9c8b1bSJoseph Chen #if defined(CONFIG_PWRKEY_DNL_TRIGGER_NUM) && \ 2371a9c8b1bSJoseph Chen (CONFIG_PWRKEY_DNL_TRIGGER_NUM > 0) 2381a9c8b1bSJoseph Chen static void power_key_download(struct dm_key_uclass_platdata *uc_key) 2391a9c8b1bSJoseph Chen { 2401a9c8b1bSJoseph Chen int trig_cnt = CONFIG_PWRKEY_DNL_TRIGGER_NUM; 2411a9c8b1bSJoseph Chen static u64 old_rise_ms; 2421a9c8b1bSJoseph Chen 2431a9c8b1bSJoseph Chen if (uc_key->code == KEY_POWER && old_rise_ms != uc_key->rise_ms) { 2441a9c8b1bSJoseph Chen old_rise_ms = uc_key->rise_ms; 2451a9c8b1bSJoseph Chen uc_key->trig_cnt++; 2461a9c8b1bSJoseph Chen if (uc_key->trig_cnt >= trig_cnt) { 2471a9c8b1bSJoseph Chen printf("\nEnter download mode by pwrkey\n"); 2481a9c8b1bSJoseph Chen irq_handler_disable(uc_key->irq); 249b40ac3b4SJoseph Chen run_command("download", 0); 2501a9c8b1bSJoseph Chen } 2511a9c8b1bSJoseph Chen } 2521a9c8b1bSJoseph Chen } 2531a9c8b1bSJoseph Chen 2541a9c8b1bSJoseph Chen int pwrkey_download_init(void) 2551a9c8b1bSJoseph Chen { 2561a9c8b1bSJoseph Chen return (KEY_NOT_EXIST == key_read(KEY_POWER)); 2571a9c8b1bSJoseph Chen } 2581a9c8b1bSJoseph Chen #endif 2591a9c8b1bSJoseph Chen 2605a54baa7SJoseph Chen static void gpio_irq_handler(int irq, void *data) 2615a54baa7SJoseph Chen { 262c2e7a0d4SJoseph Chen struct udevice *dev = data; 263c2e7a0d4SJoseph Chen struct dm_key_uclass_platdata *uc_key = dev_get_uclass_platdata(dev); 2645a54baa7SJoseph Chen 2655a54baa7SJoseph Chen if (uc_key->irq != irq) 2665a54baa7SJoseph Chen return; 2675a54baa7SJoseph Chen 268c2e7a0d4SJoseph Chen if (uc_key->irq_thread) { 269c2e7a0d4SJoseph Chen uc_key->irq_thread(irq, data); 270c2e7a0d4SJoseph Chen } else { 2715a54baa7SJoseph Chen if (irq_get_gpio_level(irq)) { 2725a54baa7SJoseph Chen uc_key->rise_ms = key_timer(0); 273c2e7a0d4SJoseph Chen KEY_DBG("%s: key dn: %llu ms\n", 274c2e7a0d4SJoseph Chen uc_key->name, uc_key->fall_ms); 2755a54baa7SJoseph Chen } else { 2765a54baa7SJoseph Chen uc_key->fall_ms = key_timer(0); 277c2e7a0d4SJoseph Chen KEY_DBG("%s: key up: %llu ms\n", 278c2e7a0d4SJoseph Chen uc_key->name, uc_key->rise_ms); 2795a54baa7SJoseph Chen } 2805a54baa7SJoseph Chen 2815a54baa7SJoseph Chen /* Must delay */ 2825a54baa7SJoseph Chen mdelay(10); 2835a54baa7SJoseph Chen irq_revert_irq_type(irq); 2845a54baa7SJoseph Chen } 2851a9c8b1bSJoseph Chen 2861a9c8b1bSJoseph Chen /* Hook event: enter download mode by pwrkey */ 2871a9c8b1bSJoseph Chen #if defined(CONFIG_PWRKEY_DNL_TRIGGER_NUM) && \ 2881a9c8b1bSJoseph Chen (CONFIG_PWRKEY_DNL_TRIGGER_NUM > 0) 2891a9c8b1bSJoseph Chen power_key_download(uc_key); 2901a9c8b1bSJoseph Chen #endif 291c2e7a0d4SJoseph Chen } 2925a54baa7SJoseph Chen #endif 2935a54baa7SJoseph Chen 2945a54baa7SJoseph Chen int key_bind_children(struct udevice *dev, const char *drv_name) 2955a54baa7SJoseph Chen { 2965a54baa7SJoseph Chen const char *name; 2975a54baa7SJoseph Chen ofnode node; 2985a54baa7SJoseph Chen int ret; 2995a54baa7SJoseph Chen 3005a54baa7SJoseph Chen dev_for_each_subnode(node, dev) { 3015a54baa7SJoseph Chen /* 3025a54baa7SJoseph Chen * If this node has "compatible" property, this is not 3035a54baa7SJoseph Chen * a amp subnode, but a normal device. skip. 3045a54baa7SJoseph Chen */ 3055a54baa7SJoseph Chen ofnode_get_property(node, "compatible", &ret); 3065a54baa7SJoseph Chen if (ret >= 0) 3075a54baa7SJoseph Chen continue; 3085a54baa7SJoseph Chen 3095a54baa7SJoseph Chen if (ret != -FDT_ERR_NOTFOUND) 3105a54baa7SJoseph Chen return ret; 3115a54baa7SJoseph Chen 3125a54baa7SJoseph Chen name = ofnode_get_name(node); 3135a54baa7SJoseph Chen if (!name) 3145a54baa7SJoseph Chen return -EINVAL; 3155a54baa7SJoseph Chen ret = device_bind_driver_to_node(dev, drv_name, name, 3165a54baa7SJoseph Chen node, NULL); 3175a54baa7SJoseph Chen if (ret) 3185a54baa7SJoseph Chen return ret; 3195a54baa7SJoseph Chen } 3205a54baa7SJoseph Chen 3215a54baa7SJoseph Chen return 0; 3225a54baa7SJoseph Chen } 3235a54baa7SJoseph Chen 3245a54baa7SJoseph Chen static int key_post_probe(struct udevice *dev) 3255a54baa7SJoseph Chen { 3265a54baa7SJoseph Chen struct dm_key_uclass_platdata *uc_key; 3275a54baa7SJoseph Chen int ret; 32815da1b50SJoseph Chen 3295a54baa7SJoseph Chen uc_key = dev_get_uclass_platdata(dev); 3305a54baa7SJoseph Chen if (!uc_key) 3315a54baa7SJoseph Chen return -ENXIO; 3325a54baa7SJoseph Chen 3335a54baa7SJoseph Chen /* True from U-Boot key node */ 334930ceb12SJoseph Chen uc_key->pre_reloc = dev_read_bool(dev, "u-boot,dm-pre-reloc") || 335930ceb12SJoseph Chen dev_read_bool(dev, "u-boot,dm-spl"); 3365a54baa7SJoseph Chen 33715da1b50SJoseph Chen if (uc_key->type != ADC_KEY) { 3385a54baa7SJoseph Chen if (uc_key->code == KEY_POWER) { 3397cef7918SJoseph Chen #if CONFIG_IS_ENABLED(IRQ) 3405a54baa7SJoseph Chen int irq; 3415a54baa7SJoseph Chen 3420f9d23eaSJoseph Chen if (uc_key->skip_irq_init) 3430f9d23eaSJoseph Chen return 0; 3440f9d23eaSJoseph Chen 3455a54baa7SJoseph Chen irq = phandle_gpio_to_irq(uc_key->gpios[0], 3465a54baa7SJoseph Chen uc_key->gpios[1]); 3475a54baa7SJoseph Chen if (irq < 0) { 3485a54baa7SJoseph Chen KEY_ERR("%s: failed to request irq, ret=%d\n", 3495a54baa7SJoseph Chen uc_key->name, irq); 3505a54baa7SJoseph Chen return irq; 3515a54baa7SJoseph Chen } 3525a54baa7SJoseph Chen 353c2e7a0d4SJoseph Chen if (uc_key->code != KEY_POWER && uc_key->irq_thread) { 354c2e7a0d4SJoseph Chen KEY_WARN("%s: only power key can request irq thread\n", 355c2e7a0d4SJoseph Chen uc_key->name); 356c2e7a0d4SJoseph Chen return -EINVAL; 357c2e7a0d4SJoseph Chen } 358c2e7a0d4SJoseph Chen 3595a54baa7SJoseph Chen uc_key->irq = irq; 360c2e7a0d4SJoseph Chen irq_install_handler(irq, gpio_irq_handler, dev); 3615a54baa7SJoseph Chen irq_set_irq_type(irq, IRQ_TYPE_EDGE_FALLING); 3625a54baa7SJoseph Chen irq_handler_enable(irq); 3635a54baa7SJoseph Chen #else 3645a54baa7SJoseph Chen KEY_WARN("%s: no IRQ framework available\n", uc_key->name); 3655a54baa7SJoseph Chen #endif 3665a54baa7SJoseph Chen } else { 3675a54baa7SJoseph Chen ret = gpio_request_by_name(dev, "gpios", 0, 3685a54baa7SJoseph Chen &uc_key->gpio, GPIOD_IS_IN); 3695a54baa7SJoseph Chen if (ret) { 3705a54baa7SJoseph Chen KEY_ERR("%s: failed to request gpio, ret=%d\n", 3715a54baa7SJoseph Chen uc_key->name, ret); 3725a54baa7SJoseph Chen return ret; 3735a54baa7SJoseph Chen } 3749f1dd9dfSJoseph Chen } 375adba3792SJoseph Chen } 376adba3792SJoseph Chen 3775a54baa7SJoseph Chen #ifdef DEBUG 3785a54baa7SJoseph Chen printf("[%s] (%s, %s, %s):\n", uc_key->name, 3795a54baa7SJoseph Chen uc_key->type == ADC_KEY ? "ADC" : "GPIO", 3805a54baa7SJoseph Chen uc_key->pre_reloc ? "U-Boot" : "Kernel", 3815a54baa7SJoseph Chen dev->parent->name); 3825a54baa7SJoseph Chen 3835a54baa7SJoseph Chen if (uc_key->type == ADC_KEY) { 38415da1b50SJoseph Chen printf(" %s: %d (%d, %d)\n", 38515da1b50SJoseph Chen uc_key->in_volt ? "volt" : " adc", 38615da1b50SJoseph Chen uc_key->center, uc_key->min, uc_key->max); 3875a54baa7SJoseph Chen printf(" channel: %d\n\n", uc_key->channel); 3885a54baa7SJoseph Chen } else { 3895a54baa7SJoseph Chen const char *gpio_name = 3905a54baa7SJoseph Chen ofnode_get_name(ofnode_get_by_phandle(uc_key->gpios[0])); 3915a54baa7SJoseph Chen 3925a54baa7SJoseph Chen printf(" irq: %d\n", uc_key->irq); 3935a54baa7SJoseph Chen printf(" gpio[0]: %s\n", gpio_name); 3945a54baa7SJoseph Chen printf(" gpio[1]: %d\n\n", uc_key->gpios[1]); 3955a54baa7SJoseph Chen } 3965a54baa7SJoseph Chen #endif 3975a54baa7SJoseph Chen 3985a54baa7SJoseph Chen return 0; 3993fb84000SJoseph Chen } 4003fb84000SJoseph Chen 401b398a9a7SJoseph Chen UCLASS_DRIVER(key) = { 402b398a9a7SJoseph Chen .id = UCLASS_KEY, 403b398a9a7SJoseph Chen .name = "key", 4045a54baa7SJoseph Chen .post_probe = key_post_probe, 4055a54baa7SJoseph Chen .per_device_platdata_auto_alloc_size = 4065a54baa7SJoseph Chen sizeof(struct dm_key_uclass_platdata), 407b398a9a7SJoseph Chen }; 408