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 <chenjh@rock-chips.com>
This commit is contained in:
Joseph Chen 2018-07-19 19:43:59 +08:00
parent 99b8866017
commit 64048c537e
6 changed files with 350 additions and 357 deletions

View File

@ -15,19 +15,11 @@
#include <key.h>
#include <linux/input.h>
#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",
&microvolt)) {
printf("%s: failed read 'press-threshold-microvolt', ret=%d\n",
key[i].name, microvolt);
return -EINVAL;
ret = ofnode_read_u32(node, "press-threshold-microvolt",
&microvolt);
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),
};

View File

@ -19,107 +19,93 @@
#include <irq-generic.h>
#include <irq-platform.h>
#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),
};

View File

@ -4,10 +4,12 @@
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <adc.h>
#include <dm.h>
#include <key.h>
#include <common.h>
#include <dm.h>
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) = {

View File

@ -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)

View File

@ -19,54 +19,33 @@
#include <irq-generic.h>
#include <irq-platform.h>
#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),
};

View File

@ -7,10 +7,17 @@
#ifndef _KEY_H_
#define _KEY_H_
#include <asm-generic/gpio.h>
#include <dt-bindings/input/linux-event-codes.h>
#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