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