diff options
author | Jaewon Kim <jaewon02.kim@samsung.com> | 2015-04-10 22:24:46 +0900 |
---|---|---|
committer | Seung-Woo Kim <sw0312.kim@samsung.com> | 2016-12-14 13:42:51 +0900 |
commit | 86488cb49e66950ebb515cd2988d69c56bab705b (patch) | |
tree | a294b107247b0c28b1a971baf85d2414773dbfbc | |
parent | 8dfd364aa3c763968c36241ef50c06b8fcfb41b4 (diff) |
power: max77843_charger: update to support OTG VBUS control
This patch adds OTG VBUS control function via extcon framwork.
If OTG accessories attached to MUIC(Micro USB Inter), current direction
should change to reverse(Battary -> USB VBUS).
Signed-off-by: Jaewon Kim <jaewon02.kim@samsung.com>
-rw-r--r-- | drivers/power/max77843_charger.c | 70 | ||||
-rw-r--r-- | include/linux/mfd/max77843-private.h | 3 |
2 files changed, 72 insertions, 1 deletions
diff --git a/drivers/power/max77843_charger.c b/drivers/power/max77843_charger.c index 392eebc1ae84..3ec08f984620 100644 --- a/drivers/power/max77843_charger.c +++ b/drivers/power/max77843_charger.c @@ -9,6 +9,7 @@ * published bythe Free Software Foundation. */ +#include <linux/extcon.h> #include <linux/module.h> #include <linux/platform_device.h> #include <linux/power_supply.h> @@ -26,8 +27,12 @@ struct max77843_charger { struct i2c_client *client; struct regmap *regmap; struct power_supply psy; - + struct extcon_dev *edev; + struct work_struct work; + struct notifier_block otg_nb; + struct extcon_specific_cable_nb otg_cable_nb; struct max77843_charger_info *info; + int extcon_state; }; static int max77843_charger_get_max_current(struct max77843_charger *charger) @@ -438,6 +443,64 @@ static struct max77843_charger_info *max77843_charger_dt_init( return info; } +static void max77843_charger_otg_worker(struct work_struct *work) +{ + struct max77843_charger *charger = + container_of(work, struct max77843_charger, work); + + if (charger->extcon_state) { + /* OTG Cable attached */ + regmap_update_bits(charger->regmap, + MAX77843_CHG_REG_CHG_CNFG_00, + MAX77843_CHG_MODE_MASK, + MAX77843_CHG_OTG_MASK | MAX77843_CHG_BOOST_MASK); + } else { + /* OTG Cable detached */ + regmap_update_bits(charger->regmap, + MAX77843_CHG_REG_CHG_CNFG_00, + MAX77843_CHG_MODE_MASK, + MAX77843_CHG_ENABLE | MAX77843_CHG_BUCK_MASK); + } +} + +static int max77843_charger_otg_notifier(struct notifier_block *nb, + unsigned long event, void *ptr) +{ + struct max77843_charger *charger = container_of(nb, + struct max77843_charger, otg_nb); + + charger->extcon_state = event; + schedule_work(&charger->work); + + return 0; +} + +static int max77843_extcon_register(struct max77843_charger *charger) +{ + struct device_node *np = charger->dev->of_node; + struct extcon_dev *edev; + int ret; + + if (of_property_read_bool(np, "extcon")) { + charger->otg_nb.notifier_call = max77843_charger_otg_notifier; + + edev = extcon_get_edev_by_phandle(charger->dev, 0); + if (IS_ERR(charger->edev)) { + dev_dbg(charger->dev, "Cannot get extcon device\n"); + return -EPROBE_DEFER; + } + + ret = extcon_register_interest(&charger->otg_cable_nb, + edev->name, "USB-HOST", &charger->otg_nb); + if (ret < 0) { + dev_err(charger->dev, "Cannot register OTG notifier\n"); + return ret; + } + } + + return 0; +} + static int max77843_charger_probe(struct platform_device *pdev) { struct max77843 *max77843 = dev_get_drvdata(pdev->dev.parent); @@ -453,6 +516,11 @@ static int max77843_charger_probe(struct platform_device *pdev) charger->max77843 = max77843; charger->client = max77843->i2c_chg; charger->regmap = max77843->regmap_chg; + INIT_WORK(&charger->work, max77843_charger_otg_worker); + + ret = max77843_extcon_register(charger); + if (ret) + return ret; charger->info = max77843_charger_dt_init(pdev); if (IS_ERR_OR_NULL(charger->info)) diff --git a/include/linux/mfd/max77843-private.h b/include/linux/mfd/max77843-private.h index 542086c23110..a56e096eb206 100644 --- a/include/linux/mfd/max77843-private.h +++ b/include/linux/mfd/max77843-private.h @@ -278,10 +278,13 @@ enum max77843_irq_muic { #define MAX77843_CHG_OVER_CURRENT_BAT (0x06 << 4) /* MAX77843 CHG_CNFG_00 register */ +#define MAX77843_CHG_MODE_MASK 0x0f #define MAX77843_CHG_DISABLE 0x00 #define MAX77843_CHG_ENABLE 0x05 #define MAX77843_CHG_MASK 0x01 +#define MAX77843_CHG_OTG_MASK 0x02 #define MAX77843_CHG_BUCK_MASK 0x04 +#define MAX77843_CHG_BOOST_MASK 0x08 /* MAX77843 CHG_CNFG_01 register */ #define MAX77843_CHG_RESTART_THRESHOLD_100 0x00 |