input: rk8xx pwrkey: refactor to match irq chip framework
The PIMC as parent has register the interrupt controller as a irq chip, and as a children, this driver only cares about the rise/fall event. Change-Id: I934901a786b70920cd413e1fb15c8a5c372ea399 Signed-off-by: Joseph Chen <chenjh@rock-chips.com>
This commit is contained in:
parent
0f9d23ea98
commit
01c5bab161
|
|
@ -8,255 +8,69 @@
|
|||
#include <dm.h>
|
||||
#include <key.h>
|
||||
#include <linux/input.h>
|
||||
#include <power/pmic.h>
|
||||
#include <power/rk8xx_pmic.h>
|
||||
#include <irq-generic.h>
|
||||
#include <asm/arch/periph.h>
|
||||
#include <dm/pinctrl.h>
|
||||
|
||||
#define RK817_INT_STS_REG0 0xf8
|
||||
#define RK817_INT_MSK_REG0 0xf9
|
||||
#define RK817_INT_STS_REG1 0xfa
|
||||
#define RK817_INT_MSK_REG1 0xfb
|
||||
#define RK817_INT_STS_REG2 0xfc
|
||||
#define RK817_INT_MSK_REG2 0xfd
|
||||
#define RK817_PWRON_RISE_INT (1 << 1)
|
||||
#define RK817_PWRON_FALL_INT (1 << 0)
|
||||
#define RK817_PLUG_OUT_INT (1 << 1)
|
||||
|
||||
#define RK816_INT_STS_REG1 0x49
|
||||
#define RK816_INT_MSK_REG1 0x4a
|
||||
#define RK816_INT_STS_REG2 0x4c
|
||||
#define RK816_INT_MSK_REG2 0x4d
|
||||
#define RK816_INT_STS_REG3 0x4e
|
||||
#define RK816_INT_MSK_REG3 0x4f
|
||||
#define RK816_PWRON_RISE_INT (1 << 6)
|
||||
#define RK816_PWRON_FALL_INT (1 << 5)
|
||||
#define RK816_PLUG_OUT_INT (1 << 1)
|
||||
|
||||
#define RK805_INT_STS_REG 0x4c
|
||||
#define RK805_INT_MSK_REG 0x4d
|
||||
#define RK805_PWRON_RISE_INT (1 << 0)
|
||||
#define RK805_PWRON_FALL_INT (1 << 7)
|
||||
|
||||
struct rk8xx_key_priv {
|
||||
u8 key_int_sts_reg;
|
||||
u8 key_int_msk_reg;
|
||||
u8 plug_int_sts_reg;
|
||||
u8 plug_int_msk_reg;
|
||||
u8 pwron_rise_int;
|
||||
u8 pwron_fall_int;
|
||||
u8 plug_out_int;
|
||||
struct reg_data *init_reg;
|
||||
u32 init_reg_num;
|
||||
struct reg_data *irq_reg;
|
||||
u32 irq_reg_num;
|
||||
};
|
||||
|
||||
static struct reg_data rk817_init_reg[] = {
|
||||
/* only enable rise/fall interrupt, plugout */
|
||||
{ RK817_INT_MSK_REG0, 0xfc },
|
||||
{ RK817_INT_MSK_REG1, 0xfd },
|
||||
{ RK817_INT_MSK_REG2, 0xff },
|
||||
/* clear all interrupt states */
|
||||
{ RK817_INT_STS_REG0, 0xff },
|
||||
{ RK817_INT_STS_REG1, 0xff },
|
||||
{ RK817_INT_STS_REG2, 0xff },
|
||||
};
|
||||
|
||||
static struct reg_data rk817_irq_reg[] = {
|
||||
/* clear all interrupt states */
|
||||
{ RK817_INT_STS_REG0, 0xff },
|
||||
{ RK817_INT_STS_REG1, 0xff },
|
||||
{ RK817_INT_STS_REG2, 0xff },
|
||||
};
|
||||
|
||||
static struct reg_data rk816_init_reg[] = {
|
||||
/* only enable rise/fall interrupt, plugout */
|
||||
{ RK816_INT_MSK_REG1, 0x9f },
|
||||
{ RK816_INT_MSK_REG2, 0xff },
|
||||
{ RK816_INT_MSK_REG3, 0xfd },
|
||||
/* clear all interrupt states */
|
||||
{ RK816_INT_STS_REG1, 0xff },
|
||||
{ RK816_INT_STS_REG2, 0xff },
|
||||
{ RK816_INT_STS_REG3, 0xff },
|
||||
};
|
||||
|
||||
static struct reg_data rk816_irq_reg[] = {
|
||||
/* clear all interrupt states */
|
||||
{ RK816_INT_STS_REG1, 0xff },
|
||||
{ RK816_INT_STS_REG2, 0xff },
|
||||
{ RK816_INT_STS_REG3, 0xff },
|
||||
};
|
||||
|
||||
static struct reg_data rk805_irq_reg[] = {
|
||||
/* clear all interrupt states */
|
||||
{ RK805_INT_STS_REG, 0xff },
|
||||
};
|
||||
|
||||
static struct reg_data rk805_init_reg[] = {
|
||||
/* only enable rise/fall interrupt */
|
||||
{ RK805_INT_MSK_REG, 0x7e },
|
||||
/* clear all interrupt states */
|
||||
{ RK805_INT_STS_REG, 0xff },
|
||||
};
|
||||
|
||||
static void pwrkey_irq_handler(int irq, struct udevice *dev)
|
||||
static void rk8xx_pwron_rise_handler(int irq, void *data)
|
||||
{
|
||||
struct rk8xx_key_priv *priv = dev_get_priv(dev);
|
||||
struct dm_key_uclass_platdata *uc_key = dev_get_uclass_platdata(dev);
|
||||
int ret, val, i;
|
||||
struct udevice *dev = data;
|
||||
struct dm_key_uclass_platdata *key;
|
||||
|
||||
debug("%s: irq = %d\n", __func__, irq);
|
||||
key = dev_get_uclass_platdata(dev);
|
||||
key->rise_ms = key_timer(0);
|
||||
|
||||
/*
|
||||
* This plug out interrupt only used to wakeup cpu while U-Boot
|
||||
* charging and system suspend. Because we need to detect charger
|
||||
* plug out event and then shutdown system.
|
||||
*/
|
||||
if (priv->plug_int_sts_reg) {
|
||||
val = pmic_reg_read(dev->parent, priv->plug_int_sts_reg);
|
||||
if (val < 0) {
|
||||
printf("%s: i2c read failed, ret=%d\n", __func__, val);
|
||||
return;
|
||||
}
|
||||
|
||||
if (val & priv->plug_out_int)
|
||||
printf("Plug out interrupt\n");
|
||||
}
|
||||
|
||||
/* read key status */
|
||||
val = pmic_reg_read(dev->parent, priv->key_int_sts_reg);
|
||||
if (val < 0) {
|
||||
printf("%s: i2c read failed, ret=%d\n", __func__, val);
|
||||
return;
|
||||
}
|
||||
|
||||
/* fall event */
|
||||
if (val & priv->pwron_fall_int) {
|
||||
uc_key->fall_ms = key_timer(0);
|
||||
debug("%s: key down: %llu ms\n", __func__, uc_key->fall_ms);
|
||||
}
|
||||
|
||||
/* rise event */
|
||||
if (val & priv->pwron_rise_int) {
|
||||
uc_key->rise_ms = key_timer(0);
|
||||
debug("%s: key up: %llu ms\n", __func__, uc_key->rise_ms);
|
||||
}
|
||||
|
||||
/* clear intertup */
|
||||
for (i = 0; i < priv->irq_reg_num; i++) {
|
||||
ret = pmic_reg_write(dev->parent,
|
||||
priv->irq_reg[i].reg,
|
||||
priv->irq_reg[i].val);
|
||||
if (ret < 0) {
|
||||
printf("%s: i2c write reg 0x%x failed, ret=%d\n",
|
||||
__func__, priv->irq_reg[i].reg, ret);
|
||||
}
|
||||
|
||||
debug("%s: reg[0x%x] = 0x%x\n", __func__, priv->irq_reg[i].reg,
|
||||
pmic_reg_read(dev->parent, priv->irq_reg[i].reg));
|
||||
}
|
||||
debug("%s: %llu ms\n", __func__, key->rise_ms);
|
||||
}
|
||||
|
||||
static int pwrkey_interrupt_init(struct udevice *dev)
|
||||
static void rk8xx_pwron_fall_handler(int irq, void *data)
|
||||
{
|
||||
struct dm_key_uclass_platdata *uc_key = dev_get_uclass_platdata(dev);
|
||||
u32 interrupt[2], phandle;
|
||||
int ret;
|
||||
struct udevice *dev = data;
|
||||
struct dm_key_uclass_platdata *key;
|
||||
|
||||
phandle = dev_read_u32_default(dev->parent, "interrupt-parent", -1);
|
||||
if (phandle < 0) {
|
||||
printf("read 'interrupt-parent' failed, ret=%d\n", phandle);
|
||||
return phandle;
|
||||
}
|
||||
key = dev_get_uclass_platdata(dev);
|
||||
key->fall_ms = key_timer(0);
|
||||
|
||||
ret = dev_read_u32_array(dev->parent, "interrupts", interrupt, 2);
|
||||
if (ret) {
|
||||
printf("read 'interrupt' failed, ret=%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
uc_key->name = "rk8xx_pwr";
|
||||
uc_key->type = GPIO_KEY;
|
||||
uc_key->code = KEY_POWER;
|
||||
uc_key->gpios[0] = phandle;
|
||||
uc_key->gpios[1] = interrupt[0];
|
||||
uc_key->irq_thread = pwrkey_irq_handler;
|
||||
|
||||
return 0;
|
||||
debug("%s: %llu ms\n", __func__, key->fall_ms);
|
||||
}
|
||||
|
||||
static int rk8xx_pwrkey_probe(struct udevice *dev)
|
||||
{
|
||||
struct rk8xx_priv *rk8xx = dev_get_priv(dev->parent);
|
||||
struct rk8xx_key_priv *priv = dev_get_priv(dev);
|
||||
int ret, i;
|
||||
struct dm_key_uclass_platdata *key = dev_get_uclass_platdata(dev);
|
||||
int fall_irq, rise_irq;
|
||||
|
||||
switch (rk8xx->variant) {
|
||||
case RK805_ID:
|
||||
priv->key_int_sts_reg = RK805_INT_STS_REG;
|
||||
priv->key_int_msk_reg = RK805_INT_MSK_REG;
|
||||
priv->pwron_rise_int = RK805_PWRON_RISE_INT;
|
||||
priv->pwron_fall_int = RK805_PWRON_FALL_INT;
|
||||
priv->init_reg = rk805_init_reg;
|
||||
priv->init_reg_num = ARRAY_SIZE(rk805_init_reg);
|
||||
priv->irq_reg = rk805_irq_reg;
|
||||
priv->irq_reg_num = ARRAY_SIZE(rk805_irq_reg);
|
||||
break;
|
||||
|
||||
case RK816_ID:
|
||||
priv->key_int_sts_reg = RK816_INT_STS_REG1;
|
||||
priv->key_int_msk_reg = RK816_INT_MSK_REG1;
|
||||
priv->plug_int_sts_reg = RK816_INT_STS_REG3;
|
||||
priv->plug_int_msk_reg = RK816_INT_MSK_REG3;
|
||||
priv->pwron_rise_int = RK816_PWRON_RISE_INT;
|
||||
priv->pwron_fall_int = RK816_PWRON_FALL_INT;
|
||||
priv->plug_out_int = RK816_PLUG_OUT_INT;
|
||||
priv->init_reg = rk816_init_reg;
|
||||
priv->init_reg_num = ARRAY_SIZE(rk816_init_reg);
|
||||
priv->irq_reg = rk816_irq_reg;
|
||||
priv->irq_reg_num = ARRAY_SIZE(rk816_irq_reg);
|
||||
break;
|
||||
case RK809_ID:
|
||||
case RK817_ID:
|
||||
priv->key_int_sts_reg = RK817_INT_STS_REG0;
|
||||
priv->key_int_msk_reg = RK817_INT_MSK_REG0;
|
||||
priv->plug_int_sts_reg = RK817_INT_STS_REG1;
|
||||
priv->plug_int_msk_reg = RK817_INT_MSK_REG1;
|
||||
priv->pwron_rise_int = RK817_PWRON_RISE_INT;
|
||||
priv->pwron_fall_int = RK817_PWRON_FALL_INT;
|
||||
priv->plug_out_int = RK817_PLUG_OUT_INT;
|
||||
priv->init_reg = rk817_init_reg;
|
||||
priv->init_reg_num = ARRAY_SIZE(rk817_init_reg);
|
||||
priv->irq_reg = rk817_irq_reg;
|
||||
priv->irq_reg_num = ARRAY_SIZE(rk817_irq_reg);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
if (!rk8xx->irq_chip) {
|
||||
printf("Failed to get parent irq chip\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/* mask and clear interrupt */
|
||||
for (i = 0; i < priv->init_reg_num; i++) {
|
||||
ret = pmic_reg_write(dev->parent,
|
||||
priv->init_reg[i].reg,
|
||||
priv->init_reg[i].val);
|
||||
if (ret < 0) {
|
||||
printf("%s: i2c write reg 0x%x failed, ret=%d\n",
|
||||
__func__, priv->init_reg[i].reg, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
debug("%s: reg[%x] = 0x%x\n", __func__, priv->init_reg[i].reg,
|
||||
pmic_reg_read(dev->parent, priv->init_reg[i].reg));
|
||||
fall_irq = virq_to_irq(rk8xx->irq_chip, RK8XX_IRQ_PWRON_FALL);
|
||||
if (fall_irq < 0) {
|
||||
printf("Failed to register pwron fall irq, ret=%d\n", fall_irq);
|
||||
return fall_irq;
|
||||
}
|
||||
|
||||
return pwrkey_interrupt_init(dev);
|
||||
rise_irq = virq_to_irq(rk8xx->irq_chip, RK8XX_IRQ_PWRON_RISE);
|
||||
if (rise_irq < 0) {
|
||||
printf("Failed to register pwron rise irq, ret=%d\n", rise_irq);
|
||||
return rise_irq;
|
||||
}
|
||||
|
||||
key->name = "rk8xx_pwr";
|
||||
key->type = GPIO_KEY;
|
||||
key->code = KEY_POWER;
|
||||
key->skip_irq_init = 1;
|
||||
|
||||
irq_install_handler(fall_irq, rk8xx_pwron_fall_handler, dev);
|
||||
irq_install_handler(rise_irq, rk8xx_pwron_rise_handler, dev);
|
||||
irq_handler_enable(fall_irq);
|
||||
irq_handler_enable(rise_irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
U_BOOT_DRIVER(rk8xx_pwrkey) = {
|
||||
.name = "rk8xx_pwrkey",
|
||||
.id = UCLASS_KEY,
|
||||
.probe = rk8xx_pwrkey_probe,
|
||||
.priv_auto_alloc_size = sizeof(struct rk8xx_key_priv),
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue