aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/power/ab8500_charger.c
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 /drivers/power/ab8500_charger.c
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>
Diffstat (limited to 'drivers/power/ab8500_charger.c')
-rw-r--r--drivers/power/ab8500_charger.c42
1 files changed, 42 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";