mfd: rn5t618: Add IRQ support
This adds support for IRQ handling in the RC5T619 which is required for properly implementing subdevices like RTC. For now only definitions for the variant RC5T619 are included. Signed-off-by: Andreas Kemnade <andreas@kemnade.info> Signed-off-by: Lee Jones <lee.jones@linaro.org>
This commit is contained in:
Родитель
361dca7d97
Коммит
0c81604516
|
@ -1058,6 +1058,7 @@ config MFD_RN5T618
|
|||
depends on OF
|
||||
select MFD_CORE
|
||||
select REGMAP_I2C
|
||||
select REGMAP_IRQ
|
||||
help
|
||||
Say yes here to add support for the Ricoh RN5T567,
|
||||
RN5T618, RC5T619 PMIC.
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/mfd/rn5t618.h>
|
||||
#include <linux/module.h>
|
||||
|
@ -46,9 +48,56 @@ static const struct regmap_config rn5t618_regmap_config = {
|
|||
.cache_type = REGCACHE_RBTREE,
|
||||
};
|
||||
|
||||
static const struct regmap_irq rc5t619_irqs[] = {
|
||||
REGMAP_IRQ_REG(RN5T618_IRQ_SYS, 0, BIT(0)),
|
||||
REGMAP_IRQ_REG(RN5T618_IRQ_DCDC, 0, BIT(1)),
|
||||
REGMAP_IRQ_REG(RN5T618_IRQ_RTC, 0, BIT(2)),
|
||||
REGMAP_IRQ_REG(RN5T618_IRQ_ADC, 0, BIT(3)),
|
||||
REGMAP_IRQ_REG(RN5T618_IRQ_GPIO, 0, BIT(4)),
|
||||
REGMAP_IRQ_REG(RN5T618_IRQ_CHG, 0, BIT(6)),
|
||||
};
|
||||
|
||||
static const struct regmap_irq_chip rc5t619_irq_chip = {
|
||||
.name = "rc5t619",
|
||||
.irqs = rc5t619_irqs,
|
||||
.num_irqs = ARRAY_SIZE(rc5t619_irqs),
|
||||
.num_regs = 1,
|
||||
.status_base = RN5T618_INTMON,
|
||||
.mask_base = RN5T618_INTEN,
|
||||
.mask_invert = true,
|
||||
};
|
||||
|
||||
static struct rn5t618 *rn5t618_pm_power_off;
|
||||
static struct notifier_block rn5t618_restart_handler;
|
||||
|
||||
static int rn5t618_irq_init(struct rn5t618 *rn5t618)
|
||||
{
|
||||
const struct regmap_irq_chip *irq_chip = NULL;
|
||||
int ret;
|
||||
|
||||
if (!rn5t618->irq)
|
||||
return 0;
|
||||
|
||||
switch (rn5t618->variant) {
|
||||
case RC5T619:
|
||||
irq_chip = &rc5t619_irq_chip;
|
||||
break;
|
||||
default:
|
||||
dev_err(rn5t618->dev, "Currently no IRQ support for variant %d\n",
|
||||
(int)rn5t618->variant);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
ret = devm_regmap_add_irq_chip(rn5t618->dev, rn5t618->regmap,
|
||||
rn5t618->irq,
|
||||
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
|
||||
0, irq_chip, &rn5t618->irq_data);
|
||||
if (ret)
|
||||
dev_err(rn5t618->dev, "Failed to register IRQ chip\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void rn5t618_trigger_poweroff_sequence(bool repower)
|
||||
{
|
||||
/* disable automatic repower-on */
|
||||
|
@ -106,6 +155,8 @@ static int rn5t618_i2c_probe(struct i2c_client *i2c,
|
|||
|
||||
i2c_set_clientdata(i2c, priv);
|
||||
priv->variant = (long)of_id->data;
|
||||
priv->irq = i2c->irq;
|
||||
priv->dev = &i2c->dev;
|
||||
|
||||
priv->regmap = devm_regmap_init_i2c(i2c, &rn5t618_regmap_config);
|
||||
if (IS_ERR(priv->regmap)) {
|
||||
|
@ -138,7 +189,7 @@ static int rn5t618_i2c_probe(struct i2c_client *i2c,
|
|||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return rn5t618_irq_init(priv);
|
||||
}
|
||||
|
||||
static int rn5t618_i2c_remove(struct i2c_client *i2c)
|
||||
|
@ -155,15 +206,40 @@ static int rn5t618_i2c_remove(struct i2c_client *i2c)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused rn5t618_i2c_suspend(struct device *dev)
|
||||
{
|
||||
struct rn5t618 *priv = dev_get_drvdata(dev);
|
||||
|
||||
if (priv->irq)
|
||||
disable_irq(priv->irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused rn5t618_i2c_resume(struct device *dev)
|
||||
{
|
||||
struct rn5t618 *priv = dev_get_drvdata(dev);
|
||||
|
||||
if (priv->irq)
|
||||
enable_irq(priv->irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id rn5t618_i2c_id[] = {
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, rn5t618_i2c_id);
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(rn5t618_i2c_dev_pm_ops,
|
||||
rn5t618_i2c_suspend,
|
||||
rn5t618_i2c_resume);
|
||||
|
||||
static struct i2c_driver rn5t618_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "rn5t618",
|
||||
.of_match_table = of_match_ptr(rn5t618_of_match),
|
||||
.pm = &rn5t618_i2c_dev_pm_ops,
|
||||
},
|
||||
.probe = rn5t618_i2c_probe,
|
||||
.remove = rn5t618_i2c_remove,
|
||||
|
|
|
@ -242,9 +242,24 @@ enum {
|
|||
RC5T619,
|
||||
};
|
||||
|
||||
/* RN5T618 IRQ definitions */
|
||||
enum {
|
||||
RN5T618_IRQ_SYS = 0,
|
||||
RN5T618_IRQ_DCDC,
|
||||
RN5T618_IRQ_RTC,
|
||||
RN5T618_IRQ_ADC,
|
||||
RN5T618_IRQ_GPIO,
|
||||
RN5T618_IRQ_CHG,
|
||||
RN5T618_NR_IRQS,
|
||||
};
|
||||
|
||||
struct rn5t618 {
|
||||
struct regmap *regmap;
|
||||
struct device *dev;
|
||||
long variant;
|
||||
|
||||
int irq;
|
||||
struct regmap_irq_chip_data *irq_data;
|
||||
};
|
||||
|
||||
#endif /* __LINUX_MFD_RN5T618_H */
|
||||
|
|
Загрузка…
Ссылка в новой задаче