From 74ec41c1c5d3c35a06848dd15997a4b0a15ebfe3 Mon Sep 17 00:00:00 2001 From: Subbaraman Narayanamurthy Date: Tue, 15 Sep 2020 13:19:35 -0700 Subject: [PATCH] power: supply: qti_battery_charger: Configure ICL and FCC post SSR/PDR When the remote subsystem restarts (SSR) or the charger firmware restarts (PDR), resend the ICL/FCC votes from clients like USB driver, thermal SW once the subsystem is up. Change-Id: Ia0da3747fdb98c7873b65c948b76f6b6a286e31c Signed-off-by: Subbaraman Narayanamurthy --- drivers/power/supply/qti_battery_charger.c | 57 +++++++++++++++++----- 1 file changed, 46 insertions(+), 11 deletions(-) diff --git a/drivers/power/supply/qti_battery_charger.c b/drivers/power/supply/qti_battery_charger.c index 3538310ae107..7219e6cc8339 100644 --- a/drivers/power/supply/qti_battery_charger.c +++ b/drivers/power/supply/qti_battery_charger.c @@ -234,6 +234,8 @@ struct battery_chg_dev { struct notifier_block reboot_notifier; u32 thermal_fcc_ua; u32 restrict_fcc_ua; + u32 last_fcc_ua; + u32 usb_icl_ua; bool restrict_chg_en; }; @@ -421,14 +423,6 @@ static void battery_chg_notify_enable(struct battery_chg_dev *bcdev) pr_err("Failed to enable notification rc=%d\n", rc); } -static void battery_chg_subsys_up_work(struct work_struct *work) -{ - struct battery_chg_dev *bcdev = container_of(work, - struct battery_chg_dev, subsys_up_work); - - battery_chg_notify_enable(bcdev); -} - static void battery_chg_state_cb(void *priv, enum pmic_glink_state state) { struct battery_chg_dev *bcdev = priv; @@ -636,6 +630,11 @@ static void battery_chg_update_usb_type_work(struct work_struct *work) return; } + /* Reset usb_icl_ua whenever USB adapter type changes */ + if (pst->prop[USB_ADAP_TYPE] != POWER_SUPPLY_USB_TYPE_SDP && + pst->prop[USB_ADAP_TYPE] != POWER_SUPPLY_USB_TYPE_PD) + bcdev->usb_icl_ua = 0; + pr_debug("usb_adap_type: %u\n", pst->prop[USB_ADAP_TYPE]); switch (pst->prop[USB_ADAP_TYPE]) { @@ -831,8 +830,10 @@ static int usb_psy_set_icl(struct battery_chg_dev *bcdev, u32 prop_id, int val) temp = UINT_MAX; rc = write_property_id(bcdev, pst, prop_id, temp); - if (!rc) + if (!rc) { pr_debug("Set ICL to %u\n", temp); + bcdev->usb_icl_ua = temp; + } return rc; } @@ -946,10 +947,12 @@ static int __battery_psy_set_charge_current(struct battery_chg_dev *bcdev, rc = write_property_id(bcdev, &bcdev->psy_list[PSY_TYPE_BATTERY], BATT_CHG_CTRL_LIM, fcc_ua); - if (rc < 0) + if (rc < 0) { pr_err("Failed to set FCC %u, rc=%d\n", fcc_ua, rc); - else + } else { pr_debug("Set FCC to %u uA\n", fcc_ua); + bcdev->last_fcc_ua = fcc_ua; + } return rc; } @@ -1128,6 +1131,38 @@ static int battery_chg_init_psy(struct battery_chg_dev *bcdev) return 0; } +static void battery_chg_subsys_up_work(struct work_struct *work) +{ + struct battery_chg_dev *bcdev = container_of(work, + struct battery_chg_dev, subsys_up_work); + int rc; + + battery_chg_notify_enable(bcdev); + + /* + * Give some time after enabling notification so that USB adapter type + * information can be obtained properly which is essential for setting + * USB ICL. + */ + msleep(200); + + if (bcdev->last_fcc_ua) { + rc = __battery_psy_set_charge_current(bcdev, + bcdev->last_fcc_ua); + if (rc < 0) + pr_err("Failed to set FCC (%u uA), rc=%d\n", + bcdev->last_fcc_ua, rc); + } + + if (bcdev->usb_icl_ua) { + rc = usb_psy_set_icl(bcdev, USB_INPUT_CURR_LIMIT, + bcdev->usb_icl_ua); + if (rc < 0) + pr_err("Failed to set ICL(%u uA), rc=%d\n", + bcdev->usb_icl_ua, rc); + } +} + static int wireless_fw_send_firmware(struct battery_chg_dev *bcdev, const struct firmware *fw) {