diff options
-rw-r--r-- | drivers/power/pm2301_charger.c | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/drivers/power/pm2301_charger.c b/drivers/power/pm2301_charger.c index eed8a89ba4f0..fde5805fdab0 100644 --- a/drivers/power/pm2301_charger.c +++ b/drivers/power/pm2301_charger.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/mfd/abx500/ux500_chargalg.h> | 29 | #include <linux/mfd/abx500/ux500_chargalg.h> |
30 | #include <linux/pm2301_charger.h> | 30 | #include <linux/pm2301_charger.h> |
31 | #include <linux/gpio.h> | 31 | #include <linux/gpio.h> |
32 | #include <linux/pm_runtime.h> | ||
32 | 33 | ||
33 | #include "pm2301_charger.h" | 34 | #include "pm2301_charger.h" |
34 | 35 | ||
@@ -36,6 +37,7 @@ | |||
36 | struct pm2xxx_charger, ac_chg) | 37 | struct pm2xxx_charger, ac_chg) |
37 | #define SLEEP_MIN 50 | 38 | #define SLEEP_MIN 50 |
38 | #define SLEEP_MAX 100 | 39 | #define SLEEP_MAX 100 |
40 | #define PM2XXX_AUTOSUSPEND_DELAY 500 | ||
39 | 41 | ||
40 | static int pm2xxx_interrupt_registers[] = { | 42 | static int pm2xxx_interrupt_registers[] = { |
41 | PM2XXX_REG_INT1, | 43 | PM2XXX_REG_INT1, |
@@ -493,6 +495,9 @@ static irqreturn_t pm2xxx_irq_int(int irq, void *data) | |||
493 | struct pm2xxx_interrupts *interrupt = pm2->pm2_int; | 495 | struct pm2xxx_interrupts *interrupt = pm2->pm2_int; |
494 | int i; | 496 | int i; |
495 | 497 | ||
498 | /* wake up the device */ | ||
499 | pm_runtime_get_sync(pm2->dev); | ||
500 | |||
496 | do { | 501 | do { |
497 | for (i = 0; i < PM2XXX_NUM_INT_REG; i++) { | 502 | for (i = 0; i < PM2XXX_NUM_INT_REG; i++) { |
498 | pm2xxx_reg_read(pm2, | 503 | pm2xxx_reg_read(pm2, |
@@ -504,6 +509,9 @@ static irqreturn_t pm2xxx_irq_int(int irq, void *data) | |||
504 | } | 509 | } |
505 | } while (gpio_get_value(pm2->pdata->gpio_irq_number) == 0); | 510 | } while (gpio_get_value(pm2->pdata->gpio_irq_number) == 0); |
506 | 511 | ||
512 | pm_runtime_mark_last_busy(pm2->dev); | ||
513 | pm_runtime_put_autosuspend(pm2->dev); | ||
514 | |||
507 | return IRQ_HANDLED; | 515 | return IRQ_HANDLED; |
508 | } | 516 | } |
509 | 517 | ||
@@ -946,6 +954,53 @@ static int pm2xxx_wall_charger_suspend(struct i2c_client *i2c_client, | |||
946 | return 0; | 954 | return 0; |
947 | } | 955 | } |
948 | 956 | ||
957 | #ifdef CONFIG_PM | ||
958 | static int pm2xxx_runtime_suspend(struct device *dev) | ||
959 | { | ||
960 | struct i2c_client *pm2xxx_i2c_client = to_i2c_client(dev); | ||
961 | struct pm2xxx_charger *pm2; | ||
962 | int ret = 0; | ||
963 | |||
964 | pm2 = (struct pm2xxx_charger *)i2c_get_clientdata(pm2xxx_i2c_client); | ||
965 | if (!pm2) { | ||
966 | dev_err(pm2->dev, "no pm2xxx_charger data supplied\n"); | ||
967 | ret = -EINVAL; | ||
968 | return ret; | ||
969 | } | ||
970 | |||
971 | clear_lpn_pin(pm2); | ||
972 | |||
973 | return ret; | ||
974 | } | ||
975 | |||
976 | static int pm2xxx_runtime_resume(struct device *dev) | ||
977 | { | ||
978 | struct i2c_client *pm2xxx_i2c_client = to_i2c_client(dev); | ||
979 | struct pm2xxx_charger *pm2; | ||
980 | int ret = 0; | ||
981 | |||
982 | pm2 = (struct pm2xxx_charger *)i2c_get_clientdata(pm2xxx_i2c_client); | ||
983 | if (!pm2) { | ||
984 | dev_err(pm2->dev, "no pm2xxx_charger data supplied\n"); | ||
985 | ret = -EINVAL; | ||
986 | return ret; | ||
987 | } | ||
988 | |||
989 | if (gpio_is_valid(pm2->lpn_pin) && gpio_get_value(pm2->lpn_pin) == 0) | ||
990 | set_lpn_pin(pm2); | ||
991 | |||
992 | return ret; | ||
993 | } | ||
994 | |||
995 | static const struct dev_pm_ops pm2xxx_pm_ops = { | ||
996 | .runtime_suspend = pm2xxx_runtime_suspend, | ||
997 | .runtime_resume = pm2xxx_runtime_resume, | ||
998 | }; | ||
999 | #define PM2XXX_PM_OPS (&pm2xxx_pm_ops) | ||
1000 | #else | ||
1001 | #define PM2XXX_PM_OPS NULL | ||
1002 | #endif | ||
1003 | |||
949 | static int pm2xxx_wall_charger_probe(struct i2c_client *i2c_client, | 1004 | static int pm2xxx_wall_charger_probe(struct i2c_client *i2c_client, |
950 | const struct i2c_device_id *id) | 1005 | const struct i2c_device_id *id) |
951 | { | 1006 | { |
@@ -1077,6 +1132,16 @@ static int pm2xxx_wall_charger_probe(struct i2c_client *i2c_client, | |||
1077 | gpio_to_irq(pm2->pdata->gpio_irq_number), ret); | 1132 | gpio_to_irq(pm2->pdata->gpio_irq_number), ret); |
1078 | goto unregister_pm2xxx_charger; | 1133 | goto unregister_pm2xxx_charger; |
1079 | } | 1134 | } |
1135 | |||
1136 | ret = pm_runtime_set_active(pm2->dev); | ||
1137 | if (ret) | ||
1138 | dev_err(pm2->dev, "set active Error\n"); | ||
1139 | |||
1140 | pm_runtime_enable(pm2->dev); | ||
1141 | pm_runtime_set_autosuspend_delay(pm2->dev, PM2XXX_AUTOSUSPEND_DELAY); | ||
1142 | pm_runtime_use_autosuspend(pm2->dev); | ||
1143 | pm_runtime_resume(pm2->dev); | ||
1144 | |||
1080 | /* pm interrupt can wake up system */ | 1145 | /* pm interrupt can wake up system */ |
1081 | ret = enable_irq_wake(gpio_to_irq(pm2->pdata->gpio_irq_number)); | 1146 | ret = enable_irq_wake(gpio_to_irq(pm2->pdata->gpio_irq_number)); |
1082 | if (ret) { | 1147 | if (ret) { |
@@ -1148,6 +1213,8 @@ static int pm2xxx_wall_charger_remove(struct i2c_client *i2c_client) | |||
1148 | { | 1213 | { |
1149 | struct pm2xxx_charger *pm2 = i2c_get_clientdata(i2c_client); | 1214 | struct pm2xxx_charger *pm2 = i2c_get_clientdata(i2c_client); |
1150 | 1215 | ||
1216 | /* Disable pm_runtime */ | ||
1217 | pm_runtime_disable(pm2->dev); | ||
1151 | /* Disable AC charging */ | 1218 | /* Disable AC charging */ |
1152 | pm2xxx_charger_ac_en(&pm2->ac_chg, false, 0, 0); | 1219 | pm2xxx_charger_ac_en(&pm2->ac_chg, false, 0, 0); |
1153 | 1220 | ||
@@ -1189,6 +1256,7 @@ static struct i2c_driver pm2xxx_charger_driver = { | |||
1189 | .driver = { | 1256 | .driver = { |
1190 | .name = "pm2xxx-wall_charger", | 1257 | .name = "pm2xxx-wall_charger", |
1191 | .owner = THIS_MODULE, | 1258 | .owner = THIS_MODULE, |
1259 | .pm = PM2XXX_PM_OPS, | ||
1192 | }, | 1260 | }, |
1193 | .id_table = pm2xxx_id, | 1261 | .id_table = pm2xxx_id, |
1194 | }; | 1262 | }; |