xref: /rk3399_rockchip-uboot/drivers/input/key-uclass.c (revision eb104afcdaefa3ee1320f8c5dae924e7aba1c6fe)
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>
9b398a9a7SJoseph Chen #include <dm.h>
1018fdcbceSJoseph Chen #include <irq-generic.h>
11b398a9a7SJoseph Chen #include <key.h>
125a54baa7SJoseph Chen #include <dm/lists.h>
1318fdcbceSJoseph Chen #include <dm/uclass-internal.h>
1464048c53SJoseph Chen 
155a54baa7SJoseph Chen #define KEY_WARN(fmt, args...)	printf("Key Warn: "fmt, ##args)
165a54baa7SJoseph Chen #define KEY_ERR(fmt, args...)	printf("Key Error: "fmt, ##args)
175a54baa7SJoseph Chen #define KEY_DBG(fmt, args...)	 debug("Key Debug: "fmt, ##args)
18adba3792SJoseph Chen 
19a2df9606SJoseph Chen static inline uint64_t arch_counter_get_cntpct(void)
20a2df9606SJoseph Chen {
21a2df9606SJoseph Chen 	uint64_t cval = 0;
22a2df9606SJoseph Chen 
23a2df9606SJoseph Chen 	isb();
24a2df9606SJoseph Chen #ifdef CONFIG_ARM64
25a2df9606SJoseph Chen 	asm volatile("mrs %0, cntpct_el0" : "=r" (cval));
26a2df9606SJoseph Chen #else
27a2df9606SJoseph Chen 	asm volatile("mrrc p15, 0, %Q0, %R0, c14" : "=r" (cval));
28a2df9606SJoseph Chen #endif
29a2df9606SJoseph Chen 	return cval;
30a2df9606SJoseph Chen }
31a2df9606SJoseph Chen 
3264048c53SJoseph Chen uint64_t key_timer(uint64_t base)
33a2df9606SJoseph Chen {
34a2df9606SJoseph Chen 	uint64_t cntpct;
35a2df9606SJoseph Chen 
36a2df9606SJoseph Chen 	cntpct = arch_counter_get_cntpct() / 24000UL;
37a2df9606SJoseph Chen 	return (cntpct > base) ? (cntpct - base) : 0;
38a2df9606SJoseph Chen }
39a2df9606SJoseph Chen 
40*eb104afcSJoseph Chen #ifdef CONFIG_ADC
415a54baa7SJoseph Chen static int key_adc_event(struct dm_key_uclass_platdata *uc_key, int adcval)
42a2df9606SJoseph Chen {
435a54baa7SJoseph Chen 	return (adcval <= uc_key->max && adcval >= uc_key->min) ?
445a54baa7SJoseph Chen 		KEY_PRESS_DOWN : KEY_PRESS_NONE;
453fb84000SJoseph Chen }
46*eb104afcSJoseph Chen #endif
473fb84000SJoseph Chen 
485a54baa7SJoseph Chen static int key_gpio_event(struct dm_key_uclass_platdata *uc_key)
493fb84000SJoseph Chen {
505a54baa7SJoseph Chen 	if (!dm_gpio_is_valid(&uc_key->gpio)) {
515a54baa7SJoseph Chen 		KEY_ERR("'%s' Invalid gpio\n", uc_key->name);
5264048c53SJoseph Chen 		return KEY_PRESS_NONE;
5364048c53SJoseph Chen 	}
5464048c53SJoseph Chen 
555a54baa7SJoseph Chen 	return dm_gpio_get_value(&uc_key->gpio) ?
565a54baa7SJoseph Chen 	       KEY_PRESS_DOWN : KEY_PRESS_NONE;
5764048c53SJoseph Chen }
5864048c53SJoseph Chen 
595a54baa7SJoseph Chen static int key_gpio_interrupt_event(struct dm_key_uclass_platdata *uc_key)
6064048c53SJoseph Chen {
615a54baa7SJoseph Chen 	int event;
623fb84000SJoseph Chen 
633fb84000SJoseph Chen 	debug("%s: %s: up=%llu, down=%llu, delta=%llu\n",
645a54baa7SJoseph Chen 	      __func__, uc_key->name, uc_key->rise_ms, uc_key->fall_ms,
655a54baa7SJoseph Chen 	      uc_key->rise_ms - uc_key->fall_ms);
663fb84000SJoseph Chen 
673fb84000SJoseph Chen 	/* Possible this is machine power-on long pressed, so ignore this */
685a54baa7SJoseph Chen 	if (uc_key->fall_ms == 0 && uc_key->rise_ms != 0) {
695a54baa7SJoseph Chen 		event = KEY_PRESS_NONE;
703fb84000SJoseph Chen 		goto out;
713fb84000SJoseph Chen 	}
723fb84000SJoseph Chen 
735a54baa7SJoseph Chen 	if ((uc_key->rise_ms > uc_key->fall_ms) &&
745a54baa7SJoseph Chen 	    (uc_key->rise_ms - uc_key->fall_ms) >= KEY_LONG_DOWN_MS) {
755a54baa7SJoseph Chen 		uc_key->rise_ms = 0;
765a54baa7SJoseph Chen 		uc_key->fall_ms = 0;
775a54baa7SJoseph Chen 		event = KEY_PRESS_LONG_DOWN;
785a54baa7SJoseph Chen 		KEY_DBG("%s key long pressed..\n", uc_key->name);
795a54baa7SJoseph Chen 	} else if (uc_key->fall_ms &&
805a54baa7SJoseph Chen 		   key_timer(uc_key->fall_ms) >= KEY_LONG_DOWN_MS) {
815a54baa7SJoseph Chen 		uc_key->rise_ms = 0;
825a54baa7SJoseph Chen 		uc_key->fall_ms = 0;
835a54baa7SJoseph Chen 		event = KEY_PRESS_LONG_DOWN;
845a54baa7SJoseph Chen 		KEY_DBG("%s key long pressed(hold)..\n", uc_key->name);
855a54baa7SJoseph Chen 	} else if ((uc_key->rise_ms > uc_key->fall_ms) &&
865a54baa7SJoseph Chen 		   (uc_key->rise_ms - uc_key->fall_ms) < KEY_LONG_DOWN_MS) {
875a54baa7SJoseph Chen 		uc_key->rise_ms = 0;
885a54baa7SJoseph Chen 		uc_key->fall_ms = 0;
895a54baa7SJoseph Chen 		event = KEY_PRESS_DOWN;
905a54baa7SJoseph Chen 		KEY_DBG("%s key short pressed..\n", uc_key->name);
9164048c53SJoseph Chen 	/* Possible in charge animation, we enable irq after fuel gauge updated */
925a54baa7SJoseph Chen 	} else if (uc_key->rise_ms && uc_key->fall_ms &&
935a54baa7SJoseph Chen 		   (uc_key->rise_ms == uc_key->fall_ms)) {
945a54baa7SJoseph Chen 		uc_key->rise_ms = 0;
955a54baa7SJoseph Chen 		uc_key->fall_ms = 0;
965a54baa7SJoseph Chen 		event = KEY_PRESS_DOWN;
975a54baa7SJoseph Chen 		KEY_DBG("%s key short pressed..\n", uc_key->name);
983fb84000SJoseph Chen 	} else {
995a54baa7SJoseph Chen 		event = KEY_PRESS_NONE;
1003fb84000SJoseph Chen 	}
1013fb84000SJoseph Chen 
1023fb84000SJoseph Chen out:
1035a54baa7SJoseph Chen 	return event;
10464048c53SJoseph Chen }
10564048c53SJoseph Chen 
1065a54baa7SJoseph Chen int key_is_pressed(int event)
10764048c53SJoseph Chen {
1085a54baa7SJoseph Chen 	return (event == KEY_PRESS_DOWN || event == KEY_PRESS_LONG_DOWN);
10964048c53SJoseph Chen }
11064048c53SJoseph Chen 
1115a54baa7SJoseph Chen static int key_core_read(struct dm_key_uclass_platdata *uc_key)
11264048c53SJoseph Chen {
113*eb104afcSJoseph Chen 	if (uc_key->type == ADC_KEY) {
114*eb104afcSJoseph Chen #ifdef CONFIG_ADC
11564048c53SJoseph Chen 		unsigned int adcval;
11664048c53SJoseph Chen 
1175a54baa7SJoseph Chen 		if (adc_channel_single_shot("saradc",
1185a54baa7SJoseph Chen 					    uc_key->channel, &adcval)) {
1195a54baa7SJoseph Chen 			KEY_ERR("%s failed to read saradc\n", uc_key->name);
1205a54baa7SJoseph Chen 			return KEY_NOT_EXIST;
12164048c53SJoseph Chen 		}
12264048c53SJoseph Chen 
1235a54baa7SJoseph Chen 		return key_adc_event(uc_key, adcval);
124*eb104afcSJoseph Chen #else
125*eb104afcSJoseph Chen 		return KEY_NOT_EXIST;
126*eb104afcSJoseph Chen #endif
1275a54baa7SJoseph Chen 	}
12864048c53SJoseph Chen 
1295a54baa7SJoseph Chen 	return (uc_key->code == KEY_POWER) ?
1305a54baa7SJoseph Chen 		key_gpio_interrupt_event(uc_key) :
1315a54baa7SJoseph Chen 		key_gpio_event(uc_key);
1329f1dd9dfSJoseph Chen }
1339f1dd9dfSJoseph Chen 
1349f1dd9dfSJoseph Chen int key_read(int code)
1359f1dd9dfSJoseph Chen {
1365a54baa7SJoseph Chen 	struct dm_key_uclass_platdata *uc_key;
1379f1dd9dfSJoseph Chen 	struct udevice *dev;
1385a54baa7SJoseph Chen 	struct uclass *uc;
1395a54baa7SJoseph Chen 	bool allow_pre_reloc = false;
1405a54baa7SJoseph Chen 	int ret, event = KEY_NOT_EXIST;
1419f1dd9dfSJoseph Chen 
1425a54baa7SJoseph Chen 	ret = uclass_get(UCLASS_KEY, &uc);
1435a54baa7SJoseph Chen 	if (ret)
1445a54baa7SJoseph Chen 		return ret;
1455a54baa7SJoseph Chen 
1465a54baa7SJoseph Chen try_again:
1479f1dd9dfSJoseph Chen 	for (uclass_first_device(UCLASS_KEY, &dev);
1489f1dd9dfSJoseph Chen 	     dev;
1499f1dd9dfSJoseph Chen 	     uclass_next_device(&dev)) {
1505a54baa7SJoseph Chen 		uc_key = dev_get_uclass_platdata(dev);
1519f1dd9dfSJoseph Chen 
1525a54baa7SJoseph Chen 		if (!allow_pre_reloc && uc_key->pre_reloc)
1539f1dd9dfSJoseph Chen 			continue;
1549f1dd9dfSJoseph Chen 
1555a54baa7SJoseph Chen 		if (uc_key->code != code)
1569f1dd9dfSJoseph Chen 			continue;
1579f1dd9dfSJoseph Chen 
1585a54baa7SJoseph Chen 		event = key_core_read(uc_key);
1595a54baa7SJoseph Chen 		if (key_is_pressed(event))
1605a54baa7SJoseph Chen 			return event;
1615a54baa7SJoseph Chen 	}
1625a54baa7SJoseph Chen 
1635a54baa7SJoseph Chen 	/* If not find valid key node from kernel, try from u-boot */
1645a54baa7SJoseph Chen 	if (event == KEY_NOT_EXIST && !allow_pre_reloc) {
1655a54baa7SJoseph Chen 		allow_pre_reloc = true;
1665a54baa7SJoseph Chen 		goto try_again;
1675a54baa7SJoseph Chen 	}
1685a54baa7SJoseph Chen 
1695a54baa7SJoseph Chen 	return event;
1705a54baa7SJoseph Chen }
1715a54baa7SJoseph Chen 
17218fdcbceSJoseph Chen int key_exist(int code)
17318fdcbceSJoseph Chen {
17418fdcbceSJoseph Chen 	struct dm_key_uclass_platdata *uc_key;
17518fdcbceSJoseph Chen 	struct udevice *dev;
17618fdcbceSJoseph Chen 
17718fdcbceSJoseph Chen 	for (uclass_find_first_device(UCLASS_KEY, &dev);
17818fdcbceSJoseph Chen 	     dev;
17918fdcbceSJoseph Chen 	     uclass_find_next_device(&dev)) {
18018fdcbceSJoseph Chen 		uc_key = dev_get_uclass_platdata(dev);
18118fdcbceSJoseph Chen 
18218fdcbceSJoseph Chen 		if (uc_key->code == code)
18318fdcbceSJoseph Chen 			return 1;
18418fdcbceSJoseph Chen 	}
18518fdcbceSJoseph Chen 
18618fdcbceSJoseph Chen 	return 0;
18718fdcbceSJoseph Chen }
18818fdcbceSJoseph Chen 
1897cef7918SJoseph Chen #if CONFIG_IS_ENABLED(IRQ)
1901a9c8b1bSJoseph Chen #if defined(CONFIG_PWRKEY_DNL_TRIGGER_NUM) && \
1911a9c8b1bSJoseph Chen 		(CONFIG_PWRKEY_DNL_TRIGGER_NUM > 0)
1921a9c8b1bSJoseph Chen static void power_key_download(struct dm_key_uclass_platdata *uc_key)
1931a9c8b1bSJoseph Chen {
1941a9c8b1bSJoseph Chen 	int trig_cnt = CONFIG_PWRKEY_DNL_TRIGGER_NUM;
1951a9c8b1bSJoseph Chen 	static u64 old_rise_ms;
1961a9c8b1bSJoseph Chen 
1971a9c8b1bSJoseph Chen 	if (uc_key->code == KEY_POWER && old_rise_ms != uc_key->rise_ms) {
1981a9c8b1bSJoseph Chen 		old_rise_ms = uc_key->rise_ms;
1991a9c8b1bSJoseph Chen 		uc_key->trig_cnt++;
2001a9c8b1bSJoseph Chen 		if (uc_key->trig_cnt >= trig_cnt) {
2011a9c8b1bSJoseph Chen 			printf("\nEnter download mode by pwrkey\n");
2021a9c8b1bSJoseph Chen 			irq_handler_disable(uc_key->irq);
203b40ac3b4SJoseph Chen 			run_command("download", 0);
2041a9c8b1bSJoseph Chen 		}
2051a9c8b1bSJoseph Chen 	}
2061a9c8b1bSJoseph Chen }
2071a9c8b1bSJoseph Chen 
2081a9c8b1bSJoseph Chen int pwrkey_download_init(void)
2091a9c8b1bSJoseph Chen {
2101a9c8b1bSJoseph Chen 	return (KEY_NOT_EXIST == key_read(KEY_POWER));
2111a9c8b1bSJoseph Chen }
2121a9c8b1bSJoseph Chen #endif
2131a9c8b1bSJoseph Chen 
2145a54baa7SJoseph Chen static void gpio_irq_handler(int irq, void *data)
2155a54baa7SJoseph Chen {
216c2e7a0d4SJoseph Chen 	struct udevice *dev = data;
217c2e7a0d4SJoseph Chen 	struct dm_key_uclass_platdata *uc_key = dev_get_uclass_platdata(dev);
2185a54baa7SJoseph Chen 
2195a54baa7SJoseph Chen 	if (uc_key->irq != irq)
2205a54baa7SJoseph Chen 		return;
2215a54baa7SJoseph Chen 
222c2e7a0d4SJoseph Chen 	if (uc_key->irq_thread) {
223c2e7a0d4SJoseph Chen 		uc_key->irq_thread(irq, data);
224c2e7a0d4SJoseph Chen 	} else {
2255a54baa7SJoseph Chen 		if (irq_get_gpio_level(irq)) {
2265a54baa7SJoseph Chen 			uc_key->rise_ms = key_timer(0);
227c2e7a0d4SJoseph Chen 			KEY_DBG("%s: key dn: %llu ms\n",
228c2e7a0d4SJoseph Chen 				uc_key->name, uc_key->fall_ms);
2295a54baa7SJoseph Chen 		} else {
2305a54baa7SJoseph Chen 			uc_key->fall_ms = key_timer(0);
231c2e7a0d4SJoseph Chen 			KEY_DBG("%s: key up: %llu ms\n",
232c2e7a0d4SJoseph Chen 				uc_key->name, uc_key->rise_ms);
2335a54baa7SJoseph Chen 		}
2345a54baa7SJoseph Chen 
2355a54baa7SJoseph Chen 		/* Must delay */
2365a54baa7SJoseph Chen 		mdelay(10);
2375a54baa7SJoseph Chen 		irq_revert_irq_type(irq);
2385a54baa7SJoseph Chen 	}
2391a9c8b1bSJoseph Chen 
2401a9c8b1bSJoseph Chen 	/* Hook event: enter download mode by pwrkey */
2411a9c8b1bSJoseph Chen #if defined(CONFIG_PWRKEY_DNL_TRIGGER_NUM) && \
2421a9c8b1bSJoseph Chen 		(CONFIG_PWRKEY_DNL_TRIGGER_NUM > 0)
2431a9c8b1bSJoseph Chen 	power_key_download(uc_key);
2441a9c8b1bSJoseph Chen #endif
245c2e7a0d4SJoseph Chen }
2465a54baa7SJoseph Chen #endif
2475a54baa7SJoseph Chen 
2485a54baa7SJoseph Chen int key_bind_children(struct udevice *dev, const char *drv_name)
2495a54baa7SJoseph Chen {
2505a54baa7SJoseph Chen 	const char *name;
2515a54baa7SJoseph Chen 	ofnode node;
2525a54baa7SJoseph Chen 	int ret;
2535a54baa7SJoseph Chen 
2545a54baa7SJoseph Chen 	dev_for_each_subnode(node, dev) {
2555a54baa7SJoseph Chen 		/*
2565a54baa7SJoseph Chen 		 * If this node has "compatible" property, this is not
2575a54baa7SJoseph Chen 		 * a amp subnode, but a normal device. skip.
2585a54baa7SJoseph Chen 		 */
2595a54baa7SJoseph Chen 		ofnode_get_property(node, "compatible", &ret);
2605a54baa7SJoseph Chen 		if (ret >= 0)
2615a54baa7SJoseph Chen 			continue;
2625a54baa7SJoseph Chen 
2635a54baa7SJoseph Chen 		if (ret != -FDT_ERR_NOTFOUND)
2645a54baa7SJoseph Chen 			return ret;
2655a54baa7SJoseph Chen 
2665a54baa7SJoseph Chen 		name = ofnode_get_name(node);
2675a54baa7SJoseph Chen 		if (!name)
2685a54baa7SJoseph Chen 			return -EINVAL;
2695a54baa7SJoseph Chen 		ret = device_bind_driver_to_node(dev, drv_name, name,
2705a54baa7SJoseph Chen 						 node, NULL);
2715a54baa7SJoseph Chen 		if (ret)
2725a54baa7SJoseph Chen 			return ret;
2735a54baa7SJoseph Chen 	}
2745a54baa7SJoseph Chen 
2755a54baa7SJoseph Chen 	return 0;
2765a54baa7SJoseph Chen }
2775a54baa7SJoseph Chen 
2785a54baa7SJoseph Chen static int key_post_probe(struct udevice *dev)
2795a54baa7SJoseph Chen {
2805a54baa7SJoseph Chen 	struct dm_key_uclass_platdata *uc_key;
2815a54baa7SJoseph Chen 	int ret;
282b08714cbSJoseph Chen #ifdef CONFIG_SARADC_ROCKCHIP_V2
283b08714cbSJoseph Chen 	int margin = 120;
284b08714cbSJoseph Chen #else
285b08714cbSJoseph Chen 	int margin = 30;
286b08714cbSJoseph Chen #endif
2875a54baa7SJoseph Chen 	uc_key = dev_get_uclass_platdata(dev);
2885a54baa7SJoseph Chen 	if (!uc_key)
2895a54baa7SJoseph Chen 		return -ENXIO;
2905a54baa7SJoseph Chen 
2915a54baa7SJoseph Chen 	/* True from U-Boot key node */
292930ceb12SJoseph Chen 	uc_key->pre_reloc = dev_read_bool(dev, "u-boot,dm-pre-reloc") ||
293930ceb12SJoseph Chen 			    dev_read_bool(dev, "u-boot,dm-spl");
2945a54baa7SJoseph Chen 
2955a54baa7SJoseph Chen 	if (uc_key->type == ADC_KEY) {
2965a54baa7SJoseph Chen 		uc_key->max = uc_key->adcval + margin;
2975a54baa7SJoseph Chen 		uc_key->min = uc_key->adcval > margin ?
2985a54baa7SJoseph Chen 					uc_key->adcval - margin : 0;
2995a54baa7SJoseph Chen 	} else {
3005a54baa7SJoseph Chen 		if (uc_key->code == KEY_POWER) {
3017cef7918SJoseph Chen #if CONFIG_IS_ENABLED(IRQ)
3025a54baa7SJoseph Chen 			int irq;
3035a54baa7SJoseph Chen 
3040f9d23eaSJoseph Chen 			if (uc_key->skip_irq_init)
3050f9d23eaSJoseph Chen 				return 0;
3060f9d23eaSJoseph Chen 
3075a54baa7SJoseph Chen 			irq = phandle_gpio_to_irq(uc_key->gpios[0],
3085a54baa7SJoseph Chen 						  uc_key->gpios[1]);
3095a54baa7SJoseph Chen 			if (irq < 0) {
3105a54baa7SJoseph Chen 				KEY_ERR("%s: failed to request irq, ret=%d\n",
3115a54baa7SJoseph Chen 					uc_key->name, irq);
3125a54baa7SJoseph Chen 				return irq;
3135a54baa7SJoseph Chen 			}
3145a54baa7SJoseph Chen 
315c2e7a0d4SJoseph Chen 			if (uc_key->code != KEY_POWER && uc_key->irq_thread) {
316c2e7a0d4SJoseph Chen 				KEY_WARN("%s: only power key can request irq thread\n",
317c2e7a0d4SJoseph Chen 					 uc_key->name);
318c2e7a0d4SJoseph Chen 				return -EINVAL;
319c2e7a0d4SJoseph Chen 			}
320c2e7a0d4SJoseph Chen 
3215a54baa7SJoseph Chen 			uc_key->irq = irq;
322c2e7a0d4SJoseph Chen 			irq_install_handler(irq, gpio_irq_handler, dev);
3235a54baa7SJoseph Chen 			irq_set_irq_type(irq, IRQ_TYPE_EDGE_FALLING);
3245a54baa7SJoseph Chen 			irq_handler_enable(irq);
3255a54baa7SJoseph Chen #else
3265a54baa7SJoseph Chen 			KEY_WARN("%s: no IRQ framework available\n", uc_key->name);
3275a54baa7SJoseph Chen #endif
3285a54baa7SJoseph Chen 		} else {
3295a54baa7SJoseph Chen 			ret = gpio_request_by_name(dev, "gpios", 0,
3305a54baa7SJoseph Chen 						   &uc_key->gpio, GPIOD_IS_IN);
3315a54baa7SJoseph Chen 			if (ret) {
3325a54baa7SJoseph Chen 				KEY_ERR("%s: failed to request gpio, ret=%d\n",
3335a54baa7SJoseph Chen 					uc_key->name, ret);
3345a54baa7SJoseph Chen 				return ret;
3355a54baa7SJoseph Chen 			}
3369f1dd9dfSJoseph Chen 		}
337adba3792SJoseph Chen 	}
338adba3792SJoseph Chen 
3395a54baa7SJoseph Chen #ifdef DEBUG
3405a54baa7SJoseph Chen 	printf("[%s] (%s, %s, %s):\n", uc_key->name,
3415a54baa7SJoseph Chen 	       uc_key->type == ADC_KEY ? "ADC" : "GPIO",
3425a54baa7SJoseph Chen 	       uc_key->pre_reloc ? "U-Boot" : "Kernel",
3435a54baa7SJoseph Chen 	       dev->parent->name);
3445a54baa7SJoseph Chen 
3455a54baa7SJoseph Chen 	if (uc_key->type == ADC_KEY) {
3465a54baa7SJoseph Chen 		printf("    adcval: %d (%d, %d)\n", uc_key->adcval,
3475a54baa7SJoseph Chen 		       uc_key->min, uc_key->max);
3485a54baa7SJoseph Chen 		printf("   channel: %d\n\n", uc_key->channel);
3495a54baa7SJoseph Chen 	} else {
3505a54baa7SJoseph Chen 		const char *gpio_name =
3515a54baa7SJoseph Chen 		     ofnode_get_name(ofnode_get_by_phandle(uc_key->gpios[0]));
3525a54baa7SJoseph Chen 
3535a54baa7SJoseph Chen 		printf("       irq: %d\n", uc_key->irq);
3545a54baa7SJoseph Chen 		printf("   gpio[0]: %s\n", gpio_name);
3555a54baa7SJoseph Chen 		printf("   gpio[1]: %d\n\n", uc_key->gpios[1]);
3565a54baa7SJoseph Chen 	}
3575a54baa7SJoseph Chen #endif
3585a54baa7SJoseph Chen 
3595a54baa7SJoseph Chen 	return 0;
3603fb84000SJoseph Chen }
3613fb84000SJoseph Chen 
362b398a9a7SJoseph Chen UCLASS_DRIVER(key) = {
363b398a9a7SJoseph Chen 	.id		= UCLASS_KEY,
364b398a9a7SJoseph Chen 	.name		= "key",
3655a54baa7SJoseph Chen 	.post_probe	= key_post_probe,
3665a54baa7SJoseph Chen 	.per_device_platdata_auto_alloc_size =
3675a54baa7SJoseph Chen 			sizeof(struct dm_key_uclass_platdata),
368b398a9a7SJoseph Chen };
369