Commit 0c816045 authored by Andreas Kemnade's avatar Andreas Kemnade Committed by Lee Jones

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: default avatarAndreas Kemnade <andreas@kemnade.info>
Signed-off-by: default avatarLee Jones <lee.jones@linaro.org>
parent 361dca7d
...@@ -1058,6 +1058,7 @@ config MFD_RN5T618 ...@@ -1058,6 +1058,7 @@ config MFD_RN5T618
depends on OF depends on OF
select MFD_CORE select MFD_CORE
select REGMAP_I2C select REGMAP_I2C
select REGMAP_IRQ
help help
Say yes here to add support for the Ricoh RN5T567, Say yes here to add support for the Ricoh RN5T567,
RN5T618, RC5T619 PMIC. RN5T618, RC5T619 PMIC.
......
...@@ -8,6 +8,8 @@ ...@@ -8,6 +8,8 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/mfd/core.h> #include <linux/mfd/core.h>
#include <linux/mfd/rn5t618.h> #include <linux/mfd/rn5t618.h>
#include <linux/module.h> #include <linux/module.h>
...@@ -46,9 +48,56 @@ static const struct regmap_config rn5t618_regmap_config = { ...@@ -46,9 +48,56 @@ static const struct regmap_config rn5t618_regmap_config = {
.cache_type = REGCACHE_RBTREE, .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 rn5t618 *rn5t618_pm_power_off;
static struct notifier_block rn5t618_restart_handler; 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) static void rn5t618_trigger_poweroff_sequence(bool repower)
{ {
/* disable automatic repower-on */ /* disable automatic repower-on */
...@@ -106,6 +155,8 @@ static int rn5t618_i2c_probe(struct i2c_client *i2c, ...@@ -106,6 +155,8 @@ static int rn5t618_i2c_probe(struct i2c_client *i2c,
i2c_set_clientdata(i2c, priv); i2c_set_clientdata(i2c, priv);
priv->variant = (long)of_id->data; priv->variant = (long)of_id->data;
priv->irq = i2c->irq;
priv->dev = &i2c->dev;
priv->regmap = devm_regmap_init_i2c(i2c, &rn5t618_regmap_config); priv->regmap = devm_regmap_init_i2c(i2c, &rn5t618_regmap_config);
if (IS_ERR(priv->regmap)) { if (IS_ERR(priv->regmap)) {
...@@ -138,7 +189,7 @@ static int rn5t618_i2c_probe(struct i2c_client *i2c, ...@@ -138,7 +189,7 @@ static int rn5t618_i2c_probe(struct i2c_client *i2c,
return ret; return ret;
} }
return 0; return rn5t618_irq_init(priv);
} }
static int rn5t618_i2c_remove(struct i2c_client *i2c) static int rn5t618_i2c_remove(struct i2c_client *i2c)
...@@ -155,15 +206,40 @@ static int rn5t618_i2c_remove(struct i2c_client *i2c) ...@@ -155,15 +206,40 @@ static int rn5t618_i2c_remove(struct i2c_client *i2c)
return 0; 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[] = { static const struct i2c_device_id rn5t618_i2c_id[] = {
{ } { }
}; };
MODULE_DEVICE_TABLE(i2c, 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 = { static struct i2c_driver rn5t618_i2c_driver = {
.driver = { .driver = {
.name = "rn5t618", .name = "rn5t618",
.of_match_table = of_match_ptr(rn5t618_of_match), .of_match_table = of_match_ptr(rn5t618_of_match),
.pm = &rn5t618_i2c_dev_pm_ops,
}, },
.probe = rn5t618_i2c_probe, .probe = rn5t618_i2c_probe,
.remove = rn5t618_i2c_remove, .remove = rn5t618_i2c_remove,
......
...@@ -242,9 +242,24 @@ enum { ...@@ -242,9 +242,24 @@ enum {
RC5T619, 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 rn5t618 {
struct regmap *regmap; struct regmap *regmap;
struct device *dev;
long variant; long variant;
int irq;
struct regmap_irq_chip_data *irq_data;
}; };
#endif /* __LINUX_MFD_RN5T618_H */ #endif /* __LINUX_MFD_RN5T618_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment