aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLee Jones <lee.jones@linaro.org>2013-02-13 06:39:19 -0500
committerLee Jones <lee.jones@linaro.org>2013-03-06 23:35:40 -0500
commit8891716e24d7b0f4b1c3b4fdff641bcb1fb282c4 (patch)
tree4f5fbc4035d59faab6d6defee2e6f51f2bde021b
parent789ca7b46877f29b2aaa94401319c50be35b184f (diff)
ab8500-bm: Charge only mode fixes for the ab9540
Fix for charging not getting enabled in charge only mode by external charger. Signed-off-by: Lee Jones <lee.jones@linaro.org>
-rw-r--r--drivers/power/ab8500_charger.c42
-rw-r--r--drivers/power/abx500_chargalg.c14
-rw-r--r--drivers/power/pm2301_charger.c7
-rw-r--r--include/linux/mfd/abx500/ux500_chargalg.h2
4 files changed, 65 insertions, 0 deletions
diff --git a/drivers/power/ab8500_charger.c b/drivers/power/ab8500_charger.c
index 3eb23cf9ff47..f1d712308b02 100644
--- a/drivers/power/ab8500_charger.c
+++ b/drivers/power/ab8500_charger.c
@@ -15,6 +15,7 @@
15#include <linux/device.h> 15#include <linux/device.h>
16#include <linux/interrupt.h> 16#include <linux/interrupt.h>
17#include <linux/delay.h> 17#include <linux/delay.h>
18#include <linux/notifier.h>
18#include <linux/slab.h> 19#include <linux/slab.h>
19#include <linux/platform_device.h> 20#include <linux/platform_device.h>
20#include <linux/power_supply.h> 21#include <linux/power_supply.h>
@@ -97,6 +98,10 @@
97#define AB8500_SW_CONTROL_FALLBACK 0x03 98#define AB8500_SW_CONTROL_FALLBACK 0x03
98/* Wait for enumeration before charing in us */ 99/* Wait for enumeration before charing in us */
99#define WAIT_ACA_RID_ENUMERATION (5 * 1000) 100#define WAIT_ACA_RID_ENUMERATION (5 * 1000)
101/*External charger control*/
102#define AB8500_SYS_CHARGER_CONTROL_REG 0x52
103#define EXTERNAL_CHARGER_DISABLE_REG_VAL 0x03
104#define EXTERNAL_CHARGER_ENABLE_REG_VAL 0x07
100 105
101/* UsbLineStatus register - usb types */ 106/* UsbLineStatus register - usb types */
102enum ab8500_charger_link_status { 107enum ab8500_charger_link_status {
@@ -1678,6 +1683,29 @@ static int ab8500_charger_usb_en(struct ux500_charger *charger,
1678 return ret; 1683 return ret;
1679} 1684}
1680 1685
1686static int ab8500_external_charger_prepare(struct notifier_block *charger_nb,
1687 unsigned long event, void *data)
1688{
1689 int ret;
1690 struct device *dev = data;
1691 /*Toggle External charger control pin*/
1692 ret = abx500_set_register_interruptible(dev, AB8500_SYS_CTRL1_BLOCK,
1693 AB8500_SYS_CHARGER_CONTROL_REG,
1694 EXTERNAL_CHARGER_DISABLE_REG_VAL);
1695 if (ret < 0) {
1696 dev_err(dev, "write reg failed %d\n", ret);
1697 goto out;
1698 }
1699 ret = abx500_set_register_interruptible(dev, AB8500_SYS_CTRL1_BLOCK,
1700 AB8500_SYS_CHARGER_CONTROL_REG,
1701 EXTERNAL_CHARGER_ENABLE_REG_VAL);
1702 if (ret < 0)
1703 dev_err(dev, "Write reg failed %d\n", ret);
1704
1705out:
1706 return ret;
1707}
1708
1681/** 1709/**
1682 * ab8500_charger_usb_check_enable() - enable usb charging 1710 * ab8500_charger_usb_check_enable() - enable usb charging
1683 * @charger: pointer to the ux500_charger structure 1711 * @charger: pointer to the ux500_charger structure
@@ -3221,6 +3249,10 @@ static int ab8500_charger_suspend(struct platform_device *pdev,
3221#define ab8500_charger_resume NULL 3249#define ab8500_charger_resume NULL
3222#endif 3250#endif
3223 3251
3252static struct notifier_block charger_nb = {
3253 .notifier_call = ab8500_external_charger_prepare,
3254};
3255
3224static int ab8500_charger_remove(struct platform_device *pdev) 3256static int ab8500_charger_remove(struct platform_device *pdev)
3225{ 3257{
3226 struct ab8500_charger *di = platform_get_drvdata(pdev); 3258 struct ab8500_charger *di = platform_get_drvdata(pdev);
@@ -3250,6 +3282,11 @@ static int ab8500_charger_remove(struct platform_device *pdev)
3250 /* Delete the work queue */ 3282 /* Delete the work queue */
3251 destroy_workqueue(di->charger_wq); 3283 destroy_workqueue(di->charger_wq);
3252 3284
3285 /* Unregister external charger enable notifier */
3286 if (!di->ac_chg.enabled)
3287 blocking_notifier_chain_unregister(
3288 &charger_notifier_list, &charger_nb);
3289
3253 flush_scheduled_work(); 3290 flush_scheduled_work();
3254 if (di->usb_chg.enabled) 3291 if (di->usb_chg.enabled)
3255 power_supply_unregister(&di->usb_chg.psy); 3292 power_supply_unregister(&di->usb_chg.psy);
@@ -3331,6 +3368,11 @@ static int ab8500_charger_probe(struct platform_device *pdev)
3331 di->ac_chg.enabled = di->bm->ac_enabled; 3368 di->ac_chg.enabled = di->bm->ac_enabled;
3332 di->ac_chg.external = false; 3369 di->ac_chg.external = false;
3333 3370
3371 /*notifier for external charger enabling*/
3372 if (!di->ac_chg.enabled)
3373 blocking_notifier_chain_register(
3374 &charger_notifier_list, &charger_nb);
3375
3334 /* USB supply */ 3376 /* USB supply */
3335 /* power_supply base class */ 3377 /* power_supply base class */
3336 di->usb_chg.psy.name = "ab8500_usb"; 3378 di->usb_chg.psy.name = "ab8500_usb";
diff --git a/drivers/power/abx500_chargalg.c b/drivers/power/abx500_chargalg.c
index 8ab65a3a8190..a876976678ab 100644
--- a/drivers/power/abx500_chargalg.c
+++ b/drivers/power/abx500_chargalg.c
@@ -26,6 +26,7 @@
26#include <linux/mfd/abx500.h> 26#include <linux/mfd/abx500.h>
27#include <linux/mfd/abx500/ux500_chargalg.h> 27#include <linux/mfd/abx500/ux500_chargalg.h>
28#include <linux/mfd/abx500/ab8500-bm.h> 28#include <linux/mfd/abx500/ab8500-bm.h>
29#include <linux/notifier.h>
29 30
30/* Watchdog kick interval */ 31/* Watchdog kick interval */
31#define CHG_WD_INTERVAL (6 * HZ) 32#define CHG_WD_INTERVAL (6 * HZ)
@@ -243,6 +244,9 @@ struct abx500_chargalg {
243 struct kobject chargalg_kobject; 244 struct kobject chargalg_kobject;
244}; 245};
245 246
247/*External charger prepare notifier*/
248BLOCKING_NOTIFIER_HEAD(charger_notifier_list);
249
246/* Main battery properties */ 250/* Main battery properties */
247static enum power_supply_property abx500_chargalg_props[] = { 251static enum power_supply_property abx500_chargalg_props[] = {
248 POWER_SUPPLY_PROP_STATUS, 252 POWER_SUPPLY_PROP_STATUS,
@@ -503,6 +507,8 @@ static int abx500_chargalg_kick_watchdog(struct abx500_chargalg *di)
503static int abx500_chargalg_ac_en(struct abx500_chargalg *di, int enable, 507static int abx500_chargalg_ac_en(struct abx500_chargalg *di, int enable,
504 int vset, int iset) 508 int vset, int iset)
505{ 509{
510 static int abx500_chargalg_ex_ac_enable_toggle;
511
506 if (!di->ac_chg || !di->ac_chg->ops.enable) 512 if (!di->ac_chg || !di->ac_chg->ops.enable)
507 return -ENXIO; 513 return -ENXIO;
508 514
@@ -515,6 +521,14 @@ static int abx500_chargalg_ac_en(struct abx500_chargalg *di, int enable,
515 di->chg_info.ac_iset = iset; 521 di->chg_info.ac_iset = iset;
516 di->chg_info.ac_vset = vset; 522 di->chg_info.ac_vset = vset;
517 523
524 /* Enable external charger */
525 if (enable && di->ac_chg->external &&
526 !abx500_chargalg_ex_ac_enable_toggle) {
527 blocking_notifier_call_chain(&charger_notifier_list,
528 0, di->dev);
529 abx500_chargalg_ex_ac_enable_toggle++;
530 }
531
518 return di->ac_chg->ops.enable(di->ac_chg, enable, vset, iset); 532 return di->ac_chg->ops.enable(di->ac_chg, enable, vset, iset);
519} 533}
520 534
diff --git a/drivers/power/pm2301_charger.c b/drivers/power/pm2301_charger.c
index b560fa5ac4e7..45ef3b9de6b9 100644
--- a/drivers/power/pm2301_charger.c
+++ b/drivers/power/pm2301_charger.c
@@ -1059,6 +1059,13 @@ static int pm2xxx_wall_charger_probe(struct i2c_client *i2c_client,
1059 ret = pm2xxx_charger_detection(pm2, &val); 1059 ret = pm2xxx_charger_detection(pm2, &val);
1060 1060
1061 if ((ret == 0) && val) { 1061 if ((ret == 0) && val) {
1062 /*
1063 * When boot is due to AC charger plug-in,
1064 * read interrupt registers
1065 */
1066 pm2xxx_reg_read(pm2, PM2XXX_REG_INT1, &val);
1067 pm2xxx_reg_read(pm2, PM2XXX_REG_INT2, &val);
1068 pm2xxx_reg_read(pm2, PM2XXX_REG_INT4, &val);
1062 pm2->ac.charger_connected = 1; 1069 pm2->ac.charger_connected = 1;
1063 pm2->ac_conn = true; 1070 pm2->ac_conn = true;
1064 power_supply_changed(&pm2->ac_chg.psy); 1071 power_supply_changed(&pm2->ac_chg.psy);
diff --git a/include/linux/mfd/abx500/ux500_chargalg.h b/include/linux/mfd/abx500/ux500_chargalg.h
index 110d12f09548..fa831f1e8cf8 100644
--- a/include/linux/mfd/abx500/ux500_chargalg.h
+++ b/include/linux/mfd/abx500/ux500_chargalg.h
@@ -41,4 +41,6 @@ struct ux500_charger {
41 bool external; 41 bool external;
42}; 42};
43 43
44extern struct blocking_notifier_head charger_notifier_list;
45
44#endif 46#endif