aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/power/supply/axp288_charger.c81
1 files changed, 30 insertions, 51 deletions
diff --git a/drivers/power/supply/axp288_charger.c b/drivers/power/supply/axp288_charger.c
index d51ebd1da65e..54a95d196306 100644
--- a/drivers/power/supply/axp288_charger.c
+++ b/drivers/power/supply/axp288_charger.c
@@ -1,6 +1,7 @@
1/* 1/*
2 * axp288_charger.c - X-power AXP288 PMIC Charger driver 2 * axp288_charger.c - X-power AXP288 PMIC Charger driver
3 * 3 *
4 * Copyright (C) 2016-2017 Hans de Goede <hdegoede@redhat.com>
4 * Copyright (C) 2014 Intel Corporation 5 * Copyright (C) 2014 Intel Corporation
5 * Author: Ramakrishna Pallala <ramakrishna.pallala@intel.com> 6 * Author: Ramakrishna Pallala <ramakrishna.pallala@intel.com>
6 * 7 *
@@ -152,8 +153,6 @@ struct axp288_chrg_info {
152 /* SDP/CDP/DCP USB charging cable notifications */ 153 /* SDP/CDP/DCP USB charging cable notifications */
153 struct { 154 struct {
154 struct extcon_dev *edev; 155 struct extcon_dev *edev;
155 bool connected;
156 enum power_supply_type chg_type;
157 struct notifier_block nb[ARRAY_SIZE(cable_ids)]; 156 struct notifier_block nb[ARRAY_SIZE(cable_ids)];
158 struct work_struct work; 157 struct work_struct work;
159 } cable; 158 } cable;
@@ -565,66 +564,47 @@ static void axp288_charger_extcon_evt_worker(struct work_struct *work)
565 container_of(work, struct axp288_chrg_info, cable.work); 564 container_of(work, struct axp288_chrg_info, cable.work);
566 int ret, current_limit; 565 int ret, current_limit;
567 struct extcon_dev *edev = info->cable.edev; 566 struct extcon_dev *edev = info->cable.edev;
568 bool old_connected = info->cable.connected; 567 unsigned int val;
569 enum power_supply_type old_chg_type = info->cable.chg_type; 568
569 ret = regmap_read(info->regmap, AXP20X_PWR_INPUT_STATUS, &val);
570 if (ret < 0) {
571 dev_err(&info->pdev->dev, "Error reading status (%d)\n", ret);
572 return;
573 }
574
575 /* Offline? Disable charging and bail */
576 if (!(val & PS_STAT_VBUS_VALID)) {
577 dev_dbg(&info->pdev->dev, "USB charger disconnected\n");
578 mutex_lock(&info->lock);
579 axp288_charger_enable_charger(info, false);
580 mutex_unlock(&info->lock);
581 power_supply_changed(info->psy_usb);
582 return;
583 }
570 584
571 /* Determine cable/charger type */ 585 /* Determine cable/charger type */
572 if (extcon_get_state(edev, EXTCON_CHG_USB_SDP) > 0) { 586 if (extcon_get_state(edev, EXTCON_CHG_USB_SDP) > 0) {
573 dev_dbg(&info->pdev->dev, "USB SDP charger is connected"); 587 dev_dbg(&info->pdev->dev, "USB SDP charger is connected");
574 info->cable.connected = true; 588 current_limit = ILIM_500MA;
575 info->cable.chg_type = POWER_SUPPLY_TYPE_USB;
576 } else if (extcon_get_state(edev, EXTCON_CHG_USB_CDP) > 0) { 589 } else if (extcon_get_state(edev, EXTCON_CHG_USB_CDP) > 0) {
577 dev_dbg(&info->pdev->dev, "USB CDP charger is connected"); 590 dev_dbg(&info->pdev->dev, "USB CDP charger is connected");
578 info->cable.connected = true; 591 current_limit = ILIM_1500MA;
579 info->cable.chg_type = POWER_SUPPLY_TYPE_USB_CDP;
580 } else if (extcon_get_state(edev, EXTCON_CHG_USB_DCP) > 0) { 592 } else if (extcon_get_state(edev, EXTCON_CHG_USB_DCP) > 0) {
581 dev_dbg(&info->pdev->dev, "USB DCP charger is connected"); 593 dev_dbg(&info->pdev->dev, "USB DCP charger is connected");
582 info->cable.connected = true; 594 current_limit = ILIM_2000MA;
583 info->cable.chg_type = POWER_SUPPLY_TYPE_USB_DCP;
584 } else { 595 } else {
585 if (old_connected) 596 /* Charger type detection still in progress, bail. */
586 dev_dbg(&info->pdev->dev, "USB charger disconnected");
587 info->cable.connected = false;
588 info->cable.chg_type = POWER_SUPPLY_TYPE_USB;
589 }
590
591 /* Cable status changed */
592 if (old_connected == info->cable.connected &&
593 old_chg_type == info->cable.chg_type)
594 return; 597 return;
595
596 mutex_lock(&info->lock);
597
598 if (info->cable.connected) {
599 axp288_charger_enable_charger(info, false);
600
601 switch (info->cable.chg_type) {
602 case POWER_SUPPLY_TYPE_USB:
603 current_limit = ILIM_500MA;
604 break;
605 case POWER_SUPPLY_TYPE_USB_CDP:
606 current_limit = ILIM_1500MA;
607 break;
608 case POWER_SUPPLY_TYPE_USB_DCP:
609 current_limit = ILIM_2000MA;
610 break;
611 default:
612 /* Unknown */
613 current_limit = 0;
614 break;
615 }
616
617 /* Set vbus current limit first, then enable charger */
618 ret = axp288_charger_set_vbus_inlmt(info, current_limit);
619 if (ret == 0)
620 axp288_charger_enable_charger(info, true);
621 else
622 dev_err(&info->pdev->dev,
623 "error setting current limit (%d)", ret);
624 } else {
625 axp288_charger_enable_charger(info, false);
626 } 598 }
627 599
600 mutex_lock(&info->lock);
601 /* Set vbus current limit first, then enable charger */
602 ret = axp288_charger_set_vbus_inlmt(info, current_limit);
603 if (ret == 0)
604 axp288_charger_enable_charger(info, true);
605 else
606 dev_err(&info->pdev->dev,
607 "error setting current limit (%d)\n", ret);
628 mutex_unlock(&info->lock); 608 mutex_unlock(&info->lock);
629 609
630 power_supply_changed(info->psy_usb); 610 power_supply_changed(info->psy_usb);
@@ -799,7 +779,6 @@ static int axp288_charger_probe(struct platform_device *pdev)
799 info->pdev = pdev; 779 info->pdev = pdev;
800 info->regmap = axp20x->regmap; 780 info->regmap = axp20x->regmap;
801 info->regmap_irqc = axp20x->regmap_irqc; 781 info->regmap_irqc = axp20x->regmap_irqc;
802 info->cable.chg_type = -1;
803 info->is_charger_enabled = -1; 782 info->is_charger_enabled = -1;
804 783
805 info->cable.edev = extcon_get_extcon_dev(AXP288_EXTCON_DEV_NAME); 784 info->cable.edev = extcon_get_extcon_dev(AXP288_EXTCON_DEV_NAME);