diff options
-rw-r--r-- | drivers/power/supply/axp288_charger.c | 81 |
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); |