diff options
author | Lee Jones <lee.jones@linaro.org> | 2013-02-13 11:39:19 +0000 |
---|---|---|
committer | Lee Jones <lee.jones@linaro.org> | 2013-03-07 12:35:40 +0800 |
commit | 8891716e24d7b0f4b1c3b4fdff641bcb1fb282c4 (patch) | |
tree | 4f5fbc4035d59faab6d6defee2e6f51f2bde021b /drivers/power/ab8500_charger.c | |
parent | 789ca7b46877f29b2aaa94401319c50be35b184f (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.c | 42 |
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 @@ #include <linux/device.h> #include <linux/interrupt.h> #include <linux/delay.h> +#include <linux/notifier.h> #include <linux/slab.h> #include <linux/platform_device.h> #include <linux/power_supply.h> @@ -97,6 +98,10 @@ #define AB8500_SW_CONTROL_FALLBACK 0x03 /* Wait for enumeration before charing in us */ #define WAIT_ACA_RID_ENUMERATION (5 * 1000) +/*External charger control*/ +#define AB8500_SYS_CHARGER_CONTROL_REG 0x52 +#define EXTERNAL_CHARGER_DISABLE_REG_VAL 0x03 +#define EXTERNAL_CHARGER_ENABLE_REG_VAL 0x07 /* UsbLineStatus register - usb types */ enum ab8500_charger_link_status { @@ -1678,6 +1683,29 @@ static int ab8500_charger_usb_en(struct ux500_charger *charger, return ret; } +static int ab8500_external_charger_prepare(struct notifier_block *charger_nb, + unsigned long event, void *data) +{ + int ret; + struct device *dev = data; + /*Toggle External charger control pin*/ + ret = abx500_set_register_interruptible(dev, AB8500_SYS_CTRL1_BLOCK, + AB8500_SYS_CHARGER_CONTROL_REG, + EXTERNAL_CHARGER_DISABLE_REG_VAL); + if (ret < 0) { + dev_err(dev, "write reg failed %d\n", ret); + goto out; + } + ret = abx500_set_register_interruptible(dev, AB8500_SYS_CTRL1_BLOCK, + AB8500_SYS_CHARGER_CONTROL_REG, + EXTERNAL_CHARGER_ENABLE_REG_VAL); + if (ret < 0) + dev_err(dev, "Write reg failed %d\n", ret); + +out: + return ret; +} + /** * ab8500_charger_usb_check_enable() - enable usb charging * @charger: pointer to the ux500_charger structure @@ -3221,6 +3249,10 @@ static int ab8500_charger_suspend(struct platform_device *pdev, #define ab8500_charger_resume NULL #endif +static struct notifier_block charger_nb = { + .notifier_call = ab8500_external_charger_prepare, +}; + static int ab8500_charger_remove(struct platform_device *pdev) { struct ab8500_charger *di = platform_get_drvdata(pdev); @@ -3250,6 +3282,11 @@ static int ab8500_charger_remove(struct platform_device *pdev) /* Delete the work queue */ destroy_workqueue(di->charger_wq); + /* Unregister external charger enable notifier */ + if (!di->ac_chg.enabled) + blocking_notifier_chain_unregister( + &charger_notifier_list, &charger_nb); + flush_scheduled_work(); if (di->usb_chg.enabled) power_supply_unregister(&di->usb_chg.psy); @@ -3331,6 +3368,11 @@ static int ab8500_charger_probe(struct platform_device *pdev) di->ac_chg.enabled = di->bm->ac_enabled; di->ac_chg.external = false; + /*notifier for external charger enabling*/ + if (!di->ac_chg.enabled) + blocking_notifier_chain_register( + &charger_notifier_list, &charger_nb); + /* USB supply */ /* power_supply base class */ di->usb_chg.psy.name = "ab8500_usb"; |