From 64048c537e998f015febb9bde9bf1ad42d869e8f Mon Sep 17 00:00:00 2001 From: Joseph Chen Date: Thu, 19 Jul 2018 19:43:59 +0800 Subject: [PATCH] dm: key: optimise framework and update drivers 1. dm key framework takes over more generic jobs; 2. key drivers remove unused codes and match new framework; 3. only power key is registered as interrupt key; Change-Id: Icdda86f588af721b685f801ed251581f2fd85793 Signed-off-by: Joseph Chen --- drivers/input/adc_key.c | 116 +++++++--------------- drivers/input/gpio_key.c | 142 ++++++++++++-------------- drivers/input/key-uclass.c | 187 ++++++++++++++++++++++++----------- drivers/input/rk8xx_pwrkey.c | 25 +++-- drivers/input/rk_key.c | 186 ++++++++++++++-------------------- include/key.h | 51 +++++++--- 6 files changed, 350 insertions(+), 357 deletions(-) diff --git a/drivers/input/adc_key.c b/drivers/input/adc_key.c index bf25f10198..65645d01bc 100644 --- a/drivers/input/adc_key.c +++ b/drivers/input/adc_key.c @@ -15,19 +15,11 @@ #include #include -#define ADC_MARGIN 30 -#define MAX_KEY_NR 10 - -struct adc_key_priv { - u32 key_nr; -}; - static int adc_keys_ofdata_to_platdata(struct udevice *dev) { - struct adc_key_priv *priv = dev_get_priv(dev); - struct input_key *key = dev_get_platdata(dev); - u32 adc_channels[2], i = 0, microvolt; - int vref, err; + struct input_key *key; + u32 adc_channels[2], microvolt; + int vref, ret; ofnode node; /* Get vref */ @@ -39,90 +31,54 @@ static int adc_keys_ofdata_to_platdata(struct udevice *dev) } /* Get IO channel */ - err = dev_read_u32_array(dev, "io-channels", adc_channels, 2); - if (err) { - printf("failed to read 'io-channels' of %s key, ret=%d\n", - key->name, err); + ret = dev_read_u32_array(dev, "io-channels", adc_channels, 2); + if (ret) { + printf("failed to read 'io-channels', ret=%d\n", ret); return -EINVAL; } /* Parse every adc key data */ dev_for_each_subnode(node, dev) { - key[i].name = ofnode_read_string(node, "label"); - key[i].vref = vref; - key[i].margin = ADC_MARGIN; - key[i].channel = adc_channels[1]; - if (ofnode_read_u32(node, "linux,code", &key[i].code)) { + key = calloc(1, sizeof(struct input_key)); + if (!key) + return -ENOMEM; + + key->parent = dev; + key->type = ADC_KEY; + key->vref = vref; + key->channel = adc_channels[1]; + key->name = ofnode_read_string(node, "label"); + ret = ofnode_read_u32(node, "linux,code", &key->code); + if (ret) { printf("%s: failed to read 'linux,code', ret=%d\n", - key[i].name, key[i].code); - return -EINVAL; + key->name, ret); + free(key); + continue; } - if (ofnode_read_u32(node, "press-threshold-microvolt", - µvolt)) { - printf("%s: failed read 'press-threshold-microvolt', ret=%d\n", - key[i].name, microvolt); - return -EINVAL; + + ret = ofnode_read_u32(node, "press-threshold-microvolt", + µvolt); + if (ret) { + printf("%s: failed to read 'press-threshold-microvolt', ret=%d\n", + key->name, ret); + free(key); + continue; } + /* Convert microvolt to adc value */ - key[i].value = microvolt / (key[i].vref / 1024); + key->adcval = microvolt / (key->vref / 1024); + key_add(key); - debug("%s: name=%s: code=%d, vref=%d, margin=%d, channel=%d, val=%d\n", - __func__, key[i].name, key[i].code, key[i].vref, - key[i].margin, key[i].channel, key[i].value); - - /* Next node */ - i++; - priv->key_nr = i; - if (i >= MAX_KEY_NR) { - printf("Too many keys, Max support: %d\n", MAX_KEY_NR); - return -EINVAL; - } + debug("%s: name=%s: code=%d, vref=%d, channel=%d, microvolt=%d, adcval=%d\n", + __func__, key->name, key->code, key->vref, + key->channel, microvolt, key->adcval); } return 0; } -static int adc_keys_read(struct udevice *dev, int code) -{ - struct adc_key_priv *priv = dev_get_priv(dev); - struct input_key *key = dev_get_platdata(dev); - int report = KEY_NOT_EXIST; - int max, min, i = 0; - unsigned int adcval; - - for (i = 0; i < priv->key_nr; i++) { - if (key[i].code != code) - continue; - - if (adc_channel_single_shot("saradc", - key[i].channel, &adcval)) { - printf("%s: failed to read saradc\n", key[i].name); - } else { - /* Get min, max */ - max = key[i].value + key[i].margin; - if (key[i].value > key[i].margin) - min = key[i].value - key[i].margin; - else - min = key[i].value; - - /* Check */ - if ((adcval <= max) && (adcval >= min)) { - report = KEY_PRESS_DOWN; - printf("'%s' key pressed down\n", - key[i].name); - } else { - report = KEY_PRESS_NONE; - } - } - break; - } - - return report; -} - static const struct dm_key_ops key_ops = { - .name = "adc_keys", - .read = adc_keys_read, + .name = "adc-keys", }; static const struct udevice_id adc_keys_ids[] = { @@ -136,6 +92,4 @@ U_BOOT_DRIVER(adc_keys) = { .ops = &key_ops, .of_match = adc_keys_ids, .ofdata_to_platdata = adc_keys_ofdata_to_platdata, - .platdata_auto_alloc_size = sizeof(struct input_key) * MAX_KEY_NR, - .priv_auto_alloc_size = sizeof(struct adc_key_priv), }; diff --git a/drivers/input/gpio_key.c b/drivers/input/gpio_key.c index d41fef6eda..34db0d868d 100644 --- a/drivers/input/gpio_key.c +++ b/drivers/input/gpio_key.c @@ -19,107 +19,93 @@ #include #include -#define MAX_KEY_NR 10 - -struct gpio_key_priv { - u32 key_nr; -}; - static void gpio_irq_handler(int irq, void *data) { - struct udevice *dev = data; - struct gpio_key_priv *priv = dev_get_priv(dev); - struct input_key *key = dev_get_platdata(dev); - int i; + struct input_key *key = data; - for (i = 0; i < priv->key_nr; i++) { - if (key[i].irq != irq) - continue; + if (key->irq != irq) + return; - /* up event */ - if (irq_get_gpio_level(irq)) { - key[i].up_t = key_get_timer(0); - debug("%s: key down: %llu ms\n", - key[i].name, key[i].down_t); - /* down event */ - } else { - key[i].down_t = key_get_timer(0); - debug("%s: key up: %llu ms\n", - key[i].name, key[i].up_t); - } - /* Must delay */ - mdelay(10); - irq_revert_irq_type(irq); + /* up event */ + if (irq_get_gpio_level(irq)) { + key->up_t = key_timer(0); + debug("%s: key down: %llu ms\n", key->name, key->down_t); + /* down event */ + } else { + key->down_t = key_timer(0); + debug("%s: key up: %llu ms\n", key->name, key->up_t); } + /* Must delay */ + mdelay(10); + irq_revert_irq_type(irq); } static int gpio_key_ofdata_to_platdata(struct udevice *dev) { - struct gpio_key_priv *priv = dev_get_priv(dev); - struct input_key *key = dev_get_platdata(dev); - u32 gpios[2], i = 0; + struct input_key *key; + u32 gpios[2]; ofnode node; - int irq; + int irq, ret; dev_for_each_subnode(node, dev) { - key[i].name = ofnode_read_string(node, "label"); - if (ofnode_read_u32(node, "linux,code", &key[i].code)) { - printf("failed read 'linux,code' of %s key\n", - key[i].name); - return -EINVAL; - } - if (ofnode_read_u32_array(node, "gpios", gpios, 2)) { - printf("failed to read 'gpios' of %s key\n", - key[i].name); - return -EINVAL; + key = calloc(1, sizeof(struct input_key)); + if (!key) + return -ENOMEM; + + key->parent = dev; + key->type = GPIO_KEY; + key->name = ofnode_read_string(node, "label"); + ret = ofnode_read_u32(node, "linux,code", &key->code); + if (ret) { + printf("%s: failed read 'linux,code', ret=%d\n", + key->name, ret); + free(key); + continue; } - /* Must register as interrupt, be able to wakeup system */ - irq = phandle_gpio_to_irq(gpios[0], gpios[1]); - if (irq < 0) { - printf("failed to request irq for gpio, ret=%d\n", irq); - return irq; - } - key[i].irq = irq; - irq_install_handler(irq, gpio_irq_handler, dev); - irq_handler_enable(irq); - irq_set_irq_type(irq, IRQ_TYPE_EDGE_FALLING); + /* Only register power key as interrupt */ + if (key->code == KEY_POWER) { + ret = ofnode_read_u32_array(node, "gpios", gpios, 2); + if (ret) { + printf("%s: failed to read 'gpios', ret=%d\n", + key->name, ret); + free(key); + continue; + } - debug("%s: name=%s: code=%d\n", - __func__, key[i].name, key[i].code); + /* Must register as interrupt, be able to wakeup system */ + irq = phandle_gpio_to_irq(gpios[0], gpios[1]); + if (irq < 0) { + printf("%s: failed to request irq, ret=%d\n", + key->name, irq); + free(key); + continue; + } + key->irq = irq; + key_add(key); + irq_install_handler(irq, gpio_irq_handler, key); + irq_set_irq_type(irq, IRQ_TYPE_EDGE_FALLING); + irq_handler_enable(irq); + } else { + ret = gpio_request_by_name_nodev(node, "gpios", 0, + &key->gpio, + GPIOD_IS_IN); + if (ret) { + printf("%s: failed to request gpio, ret=%d\n", + key->name, ret); + } - /* Next node */ - i++; - priv->key_nr = i; - if (i >= MAX_KEY_NR) { - printf("Too many keys, Max support: %d\n", MAX_KEY_NR); - return -EINVAL; + key_add(key); } + + debug("%s: name=%s: code=%d\n", __func__, key->name, key->code); } return 0; } -static int gpio_key_read(struct udevice *dev, int code) -{ - struct gpio_key_priv *priv = dev_get_priv(dev); - struct input_key *key = dev_get_platdata(dev); - u32 report = KEY_NOT_EXIST; - int i = 0; - - for (i = 0; i < priv->key_nr; i++) { - if (key[i].code != code) - continue; - report = key_parse_gpio_event(&key[i]); - break; - } - - return report; -} - static const struct dm_key_ops key_ops = { .name = "gpio-keys", - .read = gpio_key_read, }; static const struct udevice_id gpio_key_ids[] = { @@ -133,6 +119,4 @@ U_BOOT_DRIVER(gpio_keys) = { .of_match = gpio_key_ids, .ops = &key_ops, .ofdata_to_platdata = gpio_key_ofdata_to_platdata, - .platdata_auto_alloc_size = sizeof(struct input_key) * MAX_KEY_NR, - .priv_auto_alloc_size = sizeof(struct gpio_key_priv), }; diff --git a/drivers/input/key-uclass.c b/drivers/input/key-uclass.c index efa6001311..6fc0decfab 100644 --- a/drivers/input/key-uclass.c +++ b/drivers/input/key-uclass.c @@ -4,10 +4,12 @@ * SPDX-License-Identifier: GPL-2.0+ */ +#include +#include #include #include -#include -#include + +static LIST_HEAD(key_list); static inline uint64_t arch_counter_get_cntpct(void) { @@ -22,7 +24,7 @@ static inline uint64_t arch_counter_get_cntpct(void) return cval; } -uint64_t key_get_timer(uint64_t base) +uint64_t key_timer(uint64_t base) { uint64_t cntpct; @@ -30,50 +32,51 @@ uint64_t key_get_timer(uint64_t base) return (cntpct > base) ? (cntpct - base) : 0; } -static int key_state_valid(int state) +/* + * What's simple and complex event mean? + * + * simple event: key press down or none; + * complext event: key press down, long down or none; + */ +static int key_read_adc_simple_event(struct input_key *key, unsigned int adcval) { - return (state >= KEY_PRESS_NONE && state < KEY_NOT_EXIST); -} - -static int key_read(struct udevice *dev, int code) -{ - const struct dm_key_ops *ops = dev_get_driver_ops(dev); - - if (!ops || !ops->read) - return -ENOSYS; - - return ops->read(dev, code); -} - -int key_parse_adc_event(struct input_key *key, unsigned int adcval) -{ - int report = KEY_NOT_EXIST; - int max, min; + int max, min, margin = 30; + int keyval; /* Get min, max */ - max = key->value + key->margin; - if (key->value > key->margin) - min = key->value - key->margin; + max = key->adcval + margin; + if (key->adcval > margin) + min = key->adcval - margin; else - min = key->value; + min = 0; - debug("%s: %s: max=%d, min=%d, adcval=%d\n", - __func__, key->name, max, min, adcval); + debug("%s: %s: val=%d, max=%d, min=%d, adcval=%d\n", + __func__, key->name, key->adcval, max, min, adcval); /* Check */ if ((adcval <= max) && (adcval >= min)) { - report = KEY_PRESS_DOWN; - printf("%s key pressed..\n", key->name); + keyval = KEY_PRESS_DOWN; + debug("%s key pressed..\n", key->name); } else { - report = KEY_PRESS_NONE; + keyval = KEY_PRESS_NONE; } - return report; + return keyval; } -int key_parse_gpio_event(struct input_key *key) +static int key_read_gpio_simple_event(struct input_key *key) { - u32 report = KEY_NOT_EXIST; + if (!dm_gpio_is_valid(&key->gpio)) { + printf("%s: invalid gpio\n", key->name); + return KEY_PRESS_NONE; + } + + return dm_gpio_get_value(&key->gpio) ? KEY_PRESS_DOWN : KEY_PRESS_NONE; +} + +static int key_read_gpio_complex_event(struct input_key *key) +{ + int keyval; debug("%s: %s: up=%llu, down=%llu, delta=%llu\n", __func__, key->name, key->up_t, key->down_t, @@ -81,7 +84,7 @@ int key_parse_gpio_event(struct input_key *key) /* Possible this is machine power-on long pressed, so ignore this */ if (key->down_t == 0 && key->up_t != 0) { - report = KEY_PRESS_NONE; + keyval = KEY_PRESS_NONE; goto out; } @@ -89,45 +92,113 @@ int key_parse_gpio_event(struct input_key *key) (key->up_t - key->down_t) >= KEY_LONG_DOWN_MS) { key->up_t = 0; key->down_t = 0; - report = KEY_PRESS_LONG_DOWN; - printf("%s key long pressed(hold)..\n", key->name); + keyval = KEY_PRESS_LONG_DOWN; + debug("%s key long pressed..\n", key->name); } else if (key->down_t && - key_get_timer(key->down_t) >= KEY_LONG_DOWN_MS) { + key_timer(key->down_t) >= KEY_LONG_DOWN_MS) { key->up_t = 0; key->down_t = 0; - report = KEY_PRESS_LONG_DOWN; - printf("%s key long pressed..\n", key->name); + keyval = KEY_PRESS_LONG_DOWN; + debug("%s key long pressed(hold)..\n", key->name); } else if ((key->up_t > key->down_t) && (key->up_t - key->down_t) < KEY_LONG_DOWN_MS) { key->up_t = 0; key->down_t = 0; - report = KEY_PRESS_DOWN; - printf("%s key short pressed..\n", key->name); + keyval = KEY_PRESS_DOWN; + debug("%s key short pressed..\n", key->name); + /* Possible in charge animation, we enable irq after fuel gauge updated */ + } else if (key->up_t && key->down_t && (key->up_t == key->down_t)){ + key->up_t = 0; + key->down_t = 0; + keyval = KEY_PRESS_DOWN; + debug("%s key short pressed..\n", key->name); } else { - report = KEY_PRESS_NONE; + keyval = KEY_PRESS_NONE; } out: - return report; + return keyval; +} + +static int key_read_gpio_interrupt_event(struct input_key *key) +{ + debug("%s: %s\n", __func__, key->name); + + return key_read_gpio_complex_event(key); +} + +int key_is_pressed(int keyval) +{ + return (keyval == KEY_PRESS_DOWN || keyval == KEY_PRESS_LONG_DOWN); +} + +void key_add(struct input_key *key) +{ + if (!key) + return; + + list_add_tail(&key->link, &key_list); +} + +int key_read(int code) +{ + struct udevice *dev; + struct input_key *key; + static int initialized; + unsigned int adcval; + int keyval = KEY_NOT_EXIST; + int found = 0, ret; + + /* Initialize all key drivers */ + if (!initialized) { + for (uclass_first_device(UCLASS_KEY, &dev); + dev; + uclass_next_device(&dev)) { + debug("%s: dev.name = %s\n", __func__, dev->name); + ; + } + } + + /* Search on the key list */ + list_for_each_entry(key, &key_list, link) { + if (key->code == code) { + found = 1; + break; + } + } + if (!found) + goto out; + + /* Is a adc key? */ + if (key->type & ADC_KEY) { + ret = adc_channel_single_shot("saradc", key->channel, &adcval); + if (ret) + printf("%s: failed to read saradc, ret=%d\n", + key->name, ret); + else + keyval = key_read_adc_simple_event(key, adcval); + /* Is a gpio key? */ + } else if (key->type & GPIO_KEY) { + /* All pwrkey must register as an interrupt event */ + if (key->code == KEY_POWER) { + keyval = key_read_gpio_interrupt_event(key); + } else { + keyval = key_read_gpio_simple_event(key); + } + } else { + printf("%s: invalid key type!\n", __func__); + } + + debug("%s: key.name=%s, code=%d, keyval=%d\n", + __func__, key->name, key->code, keyval); + +out: + return keyval; } int platform_key_read(int code) { - struct udevice *dev; - int report = KEY_NOT_EXIST; - - for (uclass_first_device(UCLASS_KEY, &dev); - dev; - uclass_next_device(&dev)) { - debug("key dev.name = %s, code = %d\n", dev->name, code); - report = key_read(dev, code); - if (key_state_valid(report)) { - debug("key dev.name = %s, state=%d\n", dev->name, report); - break; - } - } - - return report; + return KEY_NOT_EXIST; } UCLASS_DRIVER(key) = { diff --git a/drivers/input/rk8xx_pwrkey.c b/drivers/input/rk8xx_pwrkey.c index 3f10a2c3cb..fc3ee631e5 100644 --- a/drivers/input/rk8xx_pwrkey.c +++ b/drivers/input/rk8xx_pwrkey.c @@ -101,16 +101,6 @@ static struct reg_data rk805_init_reg[] = { { RK805_INT_STS_REG, 0xff }, }; -static int rk8xx_pwrkey_read(struct udevice *dev, int code) -{ - struct input_key *key = dev_get_platdata(dev); - - if (key->code != code) - return KEY_NOT_EXIST; - - return key_parse_gpio_event(key); -} - static void pwrkey_irq_handler(int irq, void *data) { struct udevice *dev = data; @@ -145,13 +135,13 @@ static void pwrkey_irq_handler(int irq, void *data) /* fall event */ if (val & priv->pwron_fall_int) { - key->down_t = key_get_timer(0); + key->down_t = key_timer(0); debug("%s: key down: %llu ms\n", __func__, key->down_t); } /* rise event */ if (val & priv->pwron_rise_int) { - key->up_t = key_get_timer(0); + key->up_t = key_timer(0); debug("%s: key up: %llu ms\n", __func__, key->up_t); } @@ -188,9 +178,17 @@ static int pwrkey_interrupt_init(struct udevice *dev) return ret; } - key->name = "power"; + key->parent = dev; + key->name = "rk8xx_pwrkey"; key->code = KEY_POWER; + key->type = GPIO_KEY; irq = phandle_gpio_to_irq(phandle, interrupt[0]); + if (irq < 0) { + printf("%s: failed to request irq, ret=%d\n", key->name, irq); + return irq; + } + key->irq = irq; + key_add(key); irq_install_handler(irq, pwrkey_irq_handler, dev); irq_set_irq_type(irq, IRQ_TYPE_EDGE_FALLING); irq_handler_enable(irq); @@ -200,7 +198,6 @@ static int pwrkey_interrupt_init(struct udevice *dev) static const struct dm_key_ops key_ops = { .name = "rk8xx-pwrkey", - .read = rk8xx_pwrkey_read, }; static int rk8xx_pwrkey_probe(struct udevice *dev) diff --git a/drivers/input/rk_key.c b/drivers/input/rk_key.c index cf5e7a865a..8a58e1b0e1 100644 --- a/drivers/input/rk_key.c +++ b/drivers/input/rk_key.c @@ -19,54 +19,33 @@ #include #include -#define ADC_MARGIN 30 -#define MAX_KEY_NR 10 - -struct rk_key_priv { - u32 key_nr; -}; - -enum { - INVAL_KEY = 0, - ADC_KEY, - GPIO_KEY, -}; - static void gpio_irq_handler(int irq, void *data) { - struct udevice *dev = data; - struct rk_key_priv *priv = dev_get_priv(dev); - struct input_key *key = dev_get_platdata(dev); - int i; + struct input_key *key = data; - for (i = 0; i < priv->key_nr; i++) { - if (key[i].irq != irq) - continue; + if (key->irq != irq) + return; - /* up event */ - if (irq_get_gpio_level(irq)) { - key[i].up_t = key_get_timer(0); - debug("%s: key down: %llu ms\n", - key[i].name, key[i].down_t); - /* down event */ - } else { - key[i].down_t = key_get_timer(0); - debug("%s: key up: %llu ms\n", - key[i].name, key[i].up_t); - } - /* Must delay */ - mdelay(10); - irq_revert_irq_type(irq); + /* up event */ + if (irq_get_gpio_level(irq)) { + key->up_t = key_timer(0); + debug("%s: key down: %llu ms\n", key->name, key->down_t); + /* down event */ + } else { + key->down_t = key_timer(0); + debug("%s: key up: %llu ms\n", key->name, key->up_t); } + /* Must delay */ + mdelay(10); + irq_revert_irq_type(irq); } static int rk_keys_ofdata_to_platdata(struct udevice *dev) { - struct rk_key_priv *priv = dev_get_priv(dev); - struct input_key *key = dev_get_platdata(dev); - u32 adc_channels[2], gpios[2], adcval, i = 0; + struct input_key *key; + u32 adc_channels[2], gpios[2], adcval; + int irq, ret; ofnode node; - int irq; /* Get IO channel */ if (dev_read_u32_array(dev, "io-channels", adc_channels, 2)) { @@ -75,94 +54,83 @@ static int rk_keys_ofdata_to_platdata(struct udevice *dev) } dev_for_each_subnode(node, dev) { + key = calloc(1, sizeof(struct input_key)); + if (!key) + return -ENOMEM; + /* This is an ACD key */ if (!ofnode_read_u32(node, "rockchip,adc_value", &adcval)) { - key[i].name = ofnode_read_string(node, "label"); - key[i].flag = ADC_KEY; - key[i].margin = ADC_MARGIN; - key[i].value = adcval; - key[i].channel = adc_channels[1]; - if (ofnode_read_u32(node, "linux,code", &key[i].code)) { + key->parent = dev; + key->name = ofnode_read_string(node, "label"); + key->type = ADC_KEY; + key->adcval = adcval; + key->channel = adc_channels[1]; + if (ofnode_read_u32(node, "linux,code", &key->code)) { printf("%s: failed to read 'linux,code'\n", - key[i].name); - return -EINVAL; + key->name); + free(key); + continue; } /* This is a GPIO key */ } else { - key[i].name = ofnode_read_string(node, "label"); - key[i].flag = GPIO_KEY; - if (ofnode_read_u32_array(node, "gpios", gpios, 2)) { - printf("%s: failed to read 'gpios'\n", - key[i].name); - return -EINVAL; - } - if (ofnode_read_u32(node, "linux,code", &key[i].code)) { - printf("%s: failed read 'linux,code'\n", - key[i].name); - return -EINVAL; + key->parent = dev; + key->type = GPIO_KEY; + key->name = ofnode_read_string(node, "label"); + ret = ofnode_read_u32(node, "linux,code", &key->code); + if (ret) { + printf("%s: failed read 'linux,code', ret=%d\n", + key->name, ret); + free(key); + continue; } - /* Request irq */ - irq = phandle_gpio_to_irq(gpios[0], gpios[1]); - if (irq < 0) { - printf("%s: failed to request irq, ret=%d\n", - __func__, irq); - return irq; + /* Only register power key as interrupt */ + if (key->code == KEY_POWER) { + ret = ofnode_read_u32_array(node, "gpios", + gpios, 2); + if (ret) { + printf("%s: failed to read 'gpios', ret=%d\n", + key->name, ret); + free(key); + continue; + } + + /* Request irq */ + irq = phandle_gpio_to_irq(gpios[0], gpios[1]); + if (irq < 0) { + printf("%s: failed to request irq, ret=%d\n", + __func__, irq); + free(key); + continue; + } + key->irq = irq; + key_add(key); + irq_install_handler(irq, gpio_irq_handler, key); + irq_set_irq_type(irq, IRQ_TYPE_EDGE_FALLING); + irq_handler_enable(irq); + } else { + ret = gpio_request_by_name_nodev(node, "gpios", + 0, &key->gpio, GPIOD_IS_IN); + if (ret) { + printf("%s: failed to request gpio, ret=%d\n", + key->name, ret); + free(key); + continue; + } + key_add(key); } - key[i].irq = irq; - irq_install_handler(irq, gpio_irq_handler, dev); - irq_handler_enable(irq); - irq_set_irq_type(irq, IRQ_TYPE_EDGE_FALLING); } - debug("%s: name=%s: code=%d, val=%d, channel=%d, flag=%d, margin=%d\n", - __func__, key[i].name, key[i].code, key[i].value, - key[i].channel, key[i].flag, key[i].margin); - - /* Next node */ - i++; - priv->key_nr = i; - if (i >= MAX_KEY_NR) { - printf("Too many keys, Max support: %d\n", MAX_KEY_NR); - return -EINVAL; - } + debug("%s: name=%s: code=%d, adcval=%d, channel=%d, type=%d\n", + __func__, key->name, key->code, key->adcval, + key->channel, key->type); } return 0; } -static int rk_keys_read(struct udevice *dev, int code) -{ - struct rk_key_priv *priv = dev_get_priv(dev); - struct input_key *key = dev_get_platdata(dev); - int report = KEY_NOT_EXIST; - int i = 0; - unsigned int adcval; - - for (i = 0; i < priv->key_nr; i++) { - if (key[i].code != code) - continue; - - if (key[i].flag == ADC_KEY) { - if (adc_channel_single_shot("saradc", - key[i].channel, &adcval)) { - printf("%s: failed to read saradc\n", - key[i].name); - } else { - report = key_parse_adc_event(&key[i], adcval); - } - } else { - report = key_parse_gpio_event(&key[i]); - } - break; - } - - return report; -} - static const struct dm_key_ops key_ops = { .name = "rk-keys", - .read = rk_keys_read, }; static const struct udevice_id rk_keys_ids[] = { @@ -176,6 +144,4 @@ U_BOOT_DRIVER(rk_keys) = { .ops = &key_ops, .of_match = rk_keys_ids, .ofdata_to_platdata = rk_keys_ofdata_to_platdata, - .platdata_auto_alloc_size = sizeof(struct input_key) * MAX_KEY_NR, - .priv_auto_alloc_size = sizeof(struct rk_key_priv), }; diff --git a/include/key.h b/include/key.h index ab4471b7a8..36812f748c 100644 --- a/include/key.h +++ b/include/key.h @@ -7,10 +7,17 @@ #ifndef _KEY_H_ #define _KEY_H_ +#include #include #define KEY_LONG_DOWN_MS 2000 +enum { + INVAL_KEY = 0x0, + ADC_KEY = 0x1, + GPIO_KEY = 0x2, +}; + enum key_state { KEY_PRESS_NONE, /* press without release */ KEY_PRESS_DOWN, /* press -> release */ @@ -18,30 +25,44 @@ enum key_state { KEY_NOT_EXIST, }; -struct dm_key_ops { - const char *name; - int (*read)(struct udevice *dev, int code); -}; - struct input_key { + struct udevice *parent; + struct list_head link; const char *name; u32 code; - u32 channel; - u32 value; - u32 margin; - u32 vref; - int flag; + u8 type; + /* ADC key */ + u32 adcval; + u32 vref; + u8 channel; + + /* GPIO key */ u32 irq; + struct gpio_desc gpio; + + /* Event */ u64 up_t; u64 down_t; }; -uint64_t key_get_timer(uint64_t base); +struct dm_key_ops { + const char *name; +}; + +/* Use it instead of get_timer() in key interrupt handler */ +uint64_t key_timer(uint64_t base); + +/* Reister you key to dm key framework */ +void key_add(struct input_key *key); + +/* Confirm if your key value is a press event */ +int key_is_pressed(int keyval); + +/* Read key */ +int key_read(int code); + +/* deprecated */ int platform_key_read(int code); -/* General interface for adc or gpio interrupt key event parse */ -int key_parse_gpio_event(struct input_key *key); -int key_parse_adc_event(struct input_key *key, unsigned int adcval); - #endif