Commit aee2b846 authored by Lee Jones's avatar Lee Jones

pm2301-charger: Add pm_runtime_resume & pm_runtime_suspend

To optimize the current consumption we use pm_runtime autosuspend
functions which execute the pm_runtime_suspend after a delay of
inactivity on the other hand we use pm_runtime_resume every time
we receive an interruption to wake up the pm2301.
Signed-off-by: default avatarM BenZoubeir <mustapha.ben.zoubeir-xsig@stericsson.com>
Signed-off-by: default avatarLee Jones <lee.jones@linaro.org>
Reviewed-by: default avatarPhilippe LANGLAIS <philippe.langlais@stericsson.com>
parent f4095a0f
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <linux/mfd/abx500/ux500_chargalg.h> #include <linux/mfd/abx500/ux500_chargalg.h>
#include <linux/pm2301_charger.h> #include <linux/pm2301_charger.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/pm_runtime.h>
#include "pm2301_charger.h" #include "pm2301_charger.h"
...@@ -36,6 +37,7 @@ ...@@ -36,6 +37,7 @@
struct pm2xxx_charger, ac_chg) struct pm2xxx_charger, ac_chg)
#define SLEEP_MIN 50 #define SLEEP_MIN 50
#define SLEEP_MAX 100 #define SLEEP_MAX 100
#define PM2XXX_AUTOSUSPEND_DELAY 500
static int pm2xxx_interrupt_registers[] = { static int pm2xxx_interrupt_registers[] = {
PM2XXX_REG_INT1, PM2XXX_REG_INT1,
...@@ -493,6 +495,9 @@ static irqreturn_t pm2xxx_irq_int(int irq, void *data) ...@@ -493,6 +495,9 @@ static irqreturn_t pm2xxx_irq_int(int irq, void *data)
struct pm2xxx_interrupts *interrupt = pm2->pm2_int; struct pm2xxx_interrupts *interrupt = pm2->pm2_int;
int i; int i;
/* wake up the device */
pm_runtime_get_sync(pm2->dev);
do { do {
for (i = 0; i < PM2XXX_NUM_INT_REG; i++) { for (i = 0; i < PM2XXX_NUM_INT_REG; i++) {
pm2xxx_reg_read(pm2, pm2xxx_reg_read(pm2,
...@@ -504,6 +509,9 @@ static irqreturn_t pm2xxx_irq_int(int irq, void *data) ...@@ -504,6 +509,9 @@ static irqreturn_t pm2xxx_irq_int(int irq, void *data)
} }
} while (gpio_get_value(pm2->pdata->gpio_irq_number) == 0); } while (gpio_get_value(pm2->pdata->gpio_irq_number) == 0);
pm_runtime_mark_last_busy(pm2->dev);
pm_runtime_put_autosuspend(pm2->dev);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -946,6 +954,53 @@ static int pm2xxx_wall_charger_suspend(struct i2c_client *i2c_client, ...@@ -946,6 +954,53 @@ static int pm2xxx_wall_charger_suspend(struct i2c_client *i2c_client,
return 0; return 0;
} }
#ifdef CONFIG_PM
static int pm2xxx_runtime_suspend(struct device *dev)
{
struct i2c_client *pm2xxx_i2c_client = to_i2c_client(dev);
struct pm2xxx_charger *pm2;
int ret = 0;
pm2 = (struct pm2xxx_charger *)i2c_get_clientdata(pm2xxx_i2c_client);
if (!pm2) {
dev_err(pm2->dev, "no pm2xxx_charger data supplied\n");
ret = -EINVAL;
return ret;
}
clear_lpn_pin(pm2);
return ret;
}
static int pm2xxx_runtime_resume(struct device *dev)
{
struct i2c_client *pm2xxx_i2c_client = to_i2c_client(dev);
struct pm2xxx_charger *pm2;
int ret = 0;
pm2 = (struct pm2xxx_charger *)i2c_get_clientdata(pm2xxx_i2c_client);
if (!pm2) {
dev_err(pm2->dev, "no pm2xxx_charger data supplied\n");
ret = -EINVAL;
return ret;
}
if (gpio_is_valid(pm2->lpn_pin) && gpio_get_value(pm2->lpn_pin) == 0)
set_lpn_pin(pm2);
return ret;
}
static const struct dev_pm_ops pm2xxx_pm_ops = {
.runtime_suspend = pm2xxx_runtime_suspend,
.runtime_resume = pm2xxx_runtime_resume,
};
#define PM2XXX_PM_OPS (&pm2xxx_pm_ops)
#else
#define PM2XXX_PM_OPS NULL
#endif
static int pm2xxx_wall_charger_probe(struct i2c_client *i2c_client, static int pm2xxx_wall_charger_probe(struct i2c_client *i2c_client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
...@@ -1077,6 +1132,16 @@ static int pm2xxx_wall_charger_probe(struct i2c_client *i2c_client, ...@@ -1077,6 +1132,16 @@ static int pm2xxx_wall_charger_probe(struct i2c_client *i2c_client,
gpio_to_irq(pm2->pdata->gpio_irq_number), ret); gpio_to_irq(pm2->pdata->gpio_irq_number), ret);
goto unregister_pm2xxx_charger; goto unregister_pm2xxx_charger;
} }
ret = pm_runtime_set_active(pm2->dev);
if (ret)
dev_err(pm2->dev, "set active Error\n");
pm_runtime_enable(pm2->dev);
pm_runtime_set_autosuspend_delay(pm2->dev, PM2XXX_AUTOSUSPEND_DELAY);
pm_runtime_use_autosuspend(pm2->dev);
pm_runtime_resume(pm2->dev);
/* pm interrupt can wake up system */ /* pm interrupt can wake up system */
ret = enable_irq_wake(gpio_to_irq(pm2->pdata->gpio_irq_number)); ret = enable_irq_wake(gpio_to_irq(pm2->pdata->gpio_irq_number));
if (ret) { if (ret) {
...@@ -1148,6 +1213,8 @@ static int pm2xxx_wall_charger_remove(struct i2c_client *i2c_client) ...@@ -1148,6 +1213,8 @@ static int pm2xxx_wall_charger_remove(struct i2c_client *i2c_client)
{ {
struct pm2xxx_charger *pm2 = i2c_get_clientdata(i2c_client); struct pm2xxx_charger *pm2 = i2c_get_clientdata(i2c_client);
/* Disable pm_runtime */
pm_runtime_disable(pm2->dev);
/* Disable AC charging */ /* Disable AC charging */
pm2xxx_charger_ac_en(&pm2->ac_chg, false, 0, 0); pm2xxx_charger_ac_en(&pm2->ac_chg, false, 0, 0);
...@@ -1189,6 +1256,7 @@ static struct i2c_driver pm2xxx_charger_driver = { ...@@ -1189,6 +1256,7 @@ static struct i2c_driver pm2xxx_charger_driver = {
.driver = { .driver = {
.name = "pm2xxx-wall_charger", .name = "pm2xxx-wall_charger",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pm = PM2XXX_PM_OPS,
}, },
.id_table = pm2xxx_id, .id_table = pm2xxx_id,
}; };
......
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