^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (C) ST-Ericsson SA 2012
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (c) 2012 Sony Mobile Communications AB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Charging algorithm driver for abx500 variants
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Authors:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Johan Palsson <johan.palsson@stericsson.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Karl Komierowski <karl.komierowski@stericsson.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Arun R Murthy <arun.murthy@stericsson.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Author: Imre Sunyi <imre.sunyi@sonymobile.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/hrtimer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/power_supply.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/completion.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/workqueue.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/kobject.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/mfd/core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/mfd/abx500.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/mfd/abx500/ab8500.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/mfd/abx500/ux500_chargalg.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/mfd/abx500/ab8500-bm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/notifier.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) /* Watchdog kick interval */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define CHG_WD_INTERVAL (6 * HZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) /* End-of-charge criteria counter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define EOC_COND_CNT 10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) /* One hour expressed in seconds */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define ONE_HOUR_IN_SECONDS 3600
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) /* Five minutes expressed in seconds */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define FIVE_MINUTES_IN_SECONDS 300
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define CHARGALG_CURR_STEP_LOW 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define CHARGALG_CURR_STEP_HIGH 100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) enum abx500_chargers {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) NO_CHG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) AC_CHG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) USB_CHG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) struct abx500_chargalg_charger_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) enum abx500_chargers conn_chg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) enum abx500_chargers prev_conn_chg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) enum abx500_chargers online_chg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) enum abx500_chargers prev_online_chg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) enum abx500_chargers charger_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) bool usb_chg_ok;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) bool ac_chg_ok;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) int usb_volt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) int usb_curr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) int ac_volt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) int ac_curr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) int usb_vset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) int usb_iset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) int ac_vset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) int ac_iset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) struct abx500_chargalg_suspension_status {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) bool suspended_change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) bool ac_suspended;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) bool usb_suspended;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) struct abx500_chargalg_current_step_status {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) bool curr_step_change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) int curr_step;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) struct abx500_chargalg_battery_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) int temp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) int volt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) int avg_curr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) int inst_curr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) int percent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) enum abx500_chargalg_states {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) STATE_HANDHELD_INIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) STATE_HANDHELD,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) STATE_CHG_NOT_OK_INIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) STATE_CHG_NOT_OK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) STATE_HW_TEMP_PROTECT_INIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) STATE_HW_TEMP_PROTECT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) STATE_NORMAL_INIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) STATE_NORMAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) STATE_WAIT_FOR_RECHARGE_INIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) STATE_WAIT_FOR_RECHARGE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) STATE_MAINTENANCE_A_INIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) STATE_MAINTENANCE_A,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) STATE_MAINTENANCE_B_INIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) STATE_MAINTENANCE_B,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) STATE_TEMP_UNDEROVER_INIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) STATE_TEMP_UNDEROVER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) STATE_TEMP_LOWHIGH_INIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) STATE_TEMP_LOWHIGH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) STATE_SUSPENDED_INIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) STATE_SUSPENDED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) STATE_OVV_PROTECT_INIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) STATE_OVV_PROTECT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) STATE_SAFETY_TIMER_EXPIRED_INIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) STATE_SAFETY_TIMER_EXPIRED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) STATE_BATT_REMOVED_INIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) STATE_BATT_REMOVED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) STATE_WD_EXPIRED_INIT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) STATE_WD_EXPIRED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) static const char *states[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) "HANDHELD_INIT",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) "HANDHELD",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) "CHG_NOT_OK_INIT",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) "CHG_NOT_OK",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) "HW_TEMP_PROTECT_INIT",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) "HW_TEMP_PROTECT",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) "NORMAL_INIT",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) "NORMAL",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) "WAIT_FOR_RECHARGE_INIT",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) "WAIT_FOR_RECHARGE",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) "MAINTENANCE_A_INIT",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) "MAINTENANCE_A",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) "MAINTENANCE_B_INIT",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) "MAINTENANCE_B",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) "TEMP_UNDEROVER_INIT",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) "TEMP_UNDEROVER",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) "TEMP_LOWHIGH_INIT",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) "TEMP_LOWHIGH",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) "SUSPENDED_INIT",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) "SUSPENDED",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) "OVV_PROTECT_INIT",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) "OVV_PROTECT",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) "SAFETY_TIMER_EXPIRED_INIT",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) "SAFETY_TIMER_EXPIRED",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) "BATT_REMOVED_INIT",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) "BATT_REMOVED",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) "WD_EXPIRED_INIT",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) "WD_EXPIRED",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) struct abx500_chargalg_events {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) bool batt_unknown;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) bool mainextchnotok;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) bool batt_ovv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) bool batt_rem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) bool btemp_underover;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) bool btemp_lowhigh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) bool main_thermal_prot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) bool usb_thermal_prot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) bool main_ovv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) bool vbus_ovv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) bool usbchargernotok;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) bool safety_timer_expired;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) bool maintenance_timer_expired;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) bool ac_wd_expired;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) bool usb_wd_expired;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) bool ac_cv_active;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) bool usb_cv_active;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) bool vbus_collapsed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) * struct abx500_charge_curr_maximization - Charger maximization parameters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) * @original_iset: the non optimized/maximised charger current
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) * @current_iset: the charging current used at this moment
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) * @test_delta_i: the delta between the current we want to charge and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) current that is really going into the battery
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) * @condition_cnt: number of iterations needed before a new charger current
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) is set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) * @max_current: maximum charger current
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) * @wait_cnt: to avoid too fast current step down in case of charger
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) * voltage collapse, we insert this delay between step
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) * down
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) * @level: tells in how many steps the charging current has been
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) increased
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) struct abx500_charge_curr_maximization {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) int original_iset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) int current_iset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) int test_delta_i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) int condition_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) int max_current;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) int wait_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) u8 level;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) enum maxim_ret {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) MAXIM_RET_NOACTION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) MAXIM_RET_CHANGE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) MAXIM_RET_IBAT_TOO_HIGH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) * struct abx500_chargalg - abx500 Charging algorithm device information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) * @dev: pointer to the structure device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) * @charge_status: battery operating status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) * @eoc_cnt: counter used to determine end-of_charge
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) * @maintenance_chg: indicate if maintenance charge is active
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) * @t_hyst_norm temperature hysteresis when the temperature has been
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) * over or under normal limits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) * @t_hyst_lowhigh temperature hysteresis when the temperature has been
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) * over or under the high or low limits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) * @charge_state: current state of the charging algorithm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) * @ccm charging current maximization parameters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) * @chg_info: information about connected charger types
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) * @batt_data: data of the battery
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) * @susp_status: current charger suspension status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) * @bm: Platform specific battery management information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) * @curr_status: Current step status for over-current protection
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) * @parent: pointer to the struct abx500
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) * @chargalg_psy: structure that holds the battery properties exposed by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) * the charging algorithm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) * @events: structure for information about events triggered
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) * @chargalg_wq: work queue for running the charging algorithm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) * @chargalg_periodic_work: work to run the charging algorithm periodically
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) * @chargalg_wd_work: work to kick the charger watchdog periodically
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) * @chargalg_work: work to run the charging algorithm instantly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) * @safety_timer: charging safety timer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) * @maintenance_timer: maintenance charging timer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) * @chargalg_kobject: structure of type kobject
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) struct abx500_chargalg {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) int charge_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) int eoc_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) bool maintenance_chg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) int t_hyst_norm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) int t_hyst_lowhigh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) enum abx500_chargalg_states charge_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) struct abx500_charge_curr_maximization ccm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) struct abx500_chargalg_charger_info chg_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) struct abx500_chargalg_battery_data batt_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) struct abx500_chargalg_suspension_status susp_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) struct ab8500 *parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) struct abx500_chargalg_current_step_status curr_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) struct abx500_bm_data *bm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) struct power_supply *chargalg_psy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) struct ux500_charger *ac_chg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) struct ux500_charger *usb_chg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) struct abx500_chargalg_events events;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) struct workqueue_struct *chargalg_wq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) struct delayed_work chargalg_periodic_work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) struct delayed_work chargalg_wd_work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) struct work_struct chargalg_work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) struct hrtimer safety_timer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) struct hrtimer maintenance_timer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) struct kobject chargalg_kobject;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) /*External charger prepare notifier*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) BLOCKING_NOTIFIER_HEAD(charger_notifier_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) /* Main battery properties */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) static enum power_supply_property abx500_chargalg_props[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) POWER_SUPPLY_PROP_STATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) POWER_SUPPLY_PROP_HEALTH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) struct abx500_chargalg_sysfs_entry {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) struct attribute attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) ssize_t (*show)(struct abx500_chargalg *, char *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) ssize_t (*store)(struct abx500_chargalg *, const char *, size_t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) * abx500_chargalg_safety_timer_expired() - Expiration of the safety timer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) * @timer: pointer to the hrtimer structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) * This function gets called when the safety timer for the charger
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) * expires
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) static enum hrtimer_restart
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) abx500_chargalg_safety_timer_expired(struct hrtimer *timer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) struct abx500_chargalg *di = container_of(timer, struct abx500_chargalg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) safety_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) dev_err(di->dev, "Safety timer expired\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) di->events.safety_timer_expired = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) /* Trigger execution of the algorithm instantly */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) queue_work(di->chargalg_wq, &di->chargalg_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) return HRTIMER_NORESTART;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) * abx500_chargalg_maintenance_timer_expired() - Expiration of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) * the maintenance timer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) * @timer: pointer to the timer structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) * This function gets called when the maintenence timer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) * expires
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) static enum hrtimer_restart
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) abx500_chargalg_maintenance_timer_expired(struct hrtimer *timer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) struct abx500_chargalg *di = container_of(timer, struct abx500_chargalg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) maintenance_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) dev_dbg(di->dev, "Maintenance timer expired\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) di->events.maintenance_timer_expired = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) /* Trigger execution of the algorithm instantly */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) queue_work(di->chargalg_wq, &di->chargalg_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) return HRTIMER_NORESTART;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) * abx500_chargalg_state_to() - Change charge state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) * @di: pointer to the abx500_chargalg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) * This function gets called when a charge state change should occur
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) static void abx500_chargalg_state_to(struct abx500_chargalg *di,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) enum abx500_chargalg_states state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) dev_dbg(di->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) "State changed: %s (From state: [%d] %s =to=> [%d] %s )\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) di->charge_state == state ? "NO" : "YES",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) di->charge_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) states[di->charge_state],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) states[state]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) di->charge_state = state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) static int abx500_chargalg_check_charger_enable(struct abx500_chargalg *di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) switch (di->charge_state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) case STATE_NORMAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) case STATE_MAINTENANCE_A:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) case STATE_MAINTENANCE_B:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) if (di->chg_info.charger_type & USB_CHG) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) return di->usb_chg->ops.check_enable(di->usb_chg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) di->bm->bat_type[di->bm->batt_id].normal_vol_lvl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) di->bm->bat_type[di->bm->batt_id].normal_cur_lvl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) } else if ((di->chg_info.charger_type & AC_CHG) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) !(di->ac_chg->external)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) return di->ac_chg->ops.check_enable(di->ac_chg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) di->bm->bat_type[di->bm->batt_id].normal_vol_lvl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) di->bm->bat_type[di->bm->batt_id].normal_cur_lvl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) * abx500_chargalg_check_charger_connection() - Check charger connection change
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) * @di: pointer to the abx500_chargalg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) * This function will check if there is a change in the charger connection
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) * and change charge state accordingly. AC has precedence over USB.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) static int abx500_chargalg_check_charger_connection(struct abx500_chargalg *di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) if (di->chg_info.conn_chg != di->chg_info.prev_conn_chg ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) di->susp_status.suspended_change) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) * Charger state changed or suspension
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) * has changed since last update
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) if ((di->chg_info.conn_chg & AC_CHG) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) !di->susp_status.ac_suspended) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) dev_dbg(di->dev, "Charging source is AC\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) if (di->chg_info.charger_type != AC_CHG) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) di->chg_info.charger_type = AC_CHG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) abx500_chargalg_state_to(di, STATE_NORMAL_INIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) } else if ((di->chg_info.conn_chg & USB_CHG) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) !di->susp_status.usb_suspended) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) dev_dbg(di->dev, "Charging source is USB\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) di->chg_info.charger_type = USB_CHG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) abx500_chargalg_state_to(di, STATE_NORMAL_INIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) } else if (di->chg_info.conn_chg &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) (di->susp_status.ac_suspended ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) di->susp_status.usb_suspended)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) dev_dbg(di->dev, "Charging is suspended\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) di->chg_info.charger_type = NO_CHG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) abx500_chargalg_state_to(di, STATE_SUSPENDED_INIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) dev_dbg(di->dev, "Charging source is OFF\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) di->chg_info.charger_type = NO_CHG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) abx500_chargalg_state_to(di, STATE_HANDHELD_INIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) di->chg_info.prev_conn_chg = di->chg_info.conn_chg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) di->susp_status.suspended_change = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) return di->chg_info.conn_chg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) * abx500_chargalg_check_current_step_status() - Check charging current
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) * step status.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) * @di: pointer to the abx500_chargalg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) * This function will check if there is a change in the charging current step
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) * and change charge state accordingly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) static void abx500_chargalg_check_current_step_status
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) (struct abx500_chargalg *di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) if (di->curr_status.curr_step_change)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) abx500_chargalg_state_to(di, STATE_NORMAL_INIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) di->curr_status.curr_step_change = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) * abx500_chargalg_start_safety_timer() - Start charging safety timer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) * @di: pointer to the abx500_chargalg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) * The safety timer is used to avoid overcharging of old or bad batteries.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) * There are different timers for AC and USB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) static void abx500_chargalg_start_safety_timer(struct abx500_chargalg *di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) /* Charger-dependent expiration time in hours*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) int timer_expiration = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) switch (di->chg_info.charger_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) case AC_CHG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) timer_expiration = di->bm->main_safety_tmr_h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) case USB_CHG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) timer_expiration = di->bm->usb_safety_tmr_h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) dev_err(di->dev, "Unknown charger to charge from\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) di->events.safety_timer_expired = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) hrtimer_set_expires_range(&di->safety_timer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) ktime_set(timer_expiration * ONE_HOUR_IN_SECONDS, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) ktime_set(FIVE_MINUTES_IN_SECONDS, 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) hrtimer_start_expires(&di->safety_timer, HRTIMER_MODE_REL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) * abx500_chargalg_stop_safety_timer() - Stop charging safety timer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) * @di: pointer to the abx500_chargalg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) * The safety timer is stopped whenever the NORMAL state is exited
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) static void abx500_chargalg_stop_safety_timer(struct abx500_chargalg *di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) if (hrtimer_try_to_cancel(&di->safety_timer) >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) di->events.safety_timer_expired = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) * abx500_chargalg_start_maintenance_timer() - Start charging maintenance timer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) * @di: pointer to the abx500_chargalg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) * @duration: duration of ther maintenance timer in hours
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) * The maintenance timer is used to maintain the charge in the battery once
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) * the battery is considered full. These timers are chosen to match the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) * discharge curve of the battery
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) static void abx500_chargalg_start_maintenance_timer(struct abx500_chargalg *di,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) int duration)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) hrtimer_set_expires_range(&di->maintenance_timer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) ktime_set(duration * ONE_HOUR_IN_SECONDS, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) ktime_set(FIVE_MINUTES_IN_SECONDS, 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) di->events.maintenance_timer_expired = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) hrtimer_start_expires(&di->maintenance_timer, HRTIMER_MODE_REL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) * abx500_chargalg_stop_maintenance_timer() - Stop maintenance timer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) * @di: pointer to the abx500_chargalg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) * The maintenance timer is stopped whenever maintenance ends or when another
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) * state is entered
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) static void abx500_chargalg_stop_maintenance_timer(struct abx500_chargalg *di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) if (hrtimer_try_to_cancel(&di->maintenance_timer) >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) di->events.maintenance_timer_expired = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) * abx500_chargalg_kick_watchdog() - Kick charger watchdog
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) * @di: pointer to the abx500_chargalg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) * The charger watchdog have to be kicked periodically whenever the charger is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) * on, else the ABB will reset the system
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) static int abx500_chargalg_kick_watchdog(struct abx500_chargalg *di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) /* Check if charger exists and kick watchdog if charging */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) if (di->ac_chg && di->ac_chg->ops.kick_wd &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) di->chg_info.online_chg & AC_CHG) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) * If AB charger watchdog expired, pm2xxx charging
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) * gets disabled. To be safe, kick both AB charger watchdog
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) * and pm2xxx watchdog.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) if (di->ac_chg->external &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) di->usb_chg && di->usb_chg->ops.kick_wd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) di->usb_chg->ops.kick_wd(di->usb_chg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) return di->ac_chg->ops.kick_wd(di->ac_chg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) else if (di->usb_chg && di->usb_chg->ops.kick_wd &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) di->chg_info.online_chg & USB_CHG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) return di->usb_chg->ops.kick_wd(di->usb_chg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) * abx500_chargalg_ac_en() - Turn on/off the AC charger
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) * @di: pointer to the abx500_chargalg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) * @enable: charger on/off
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) * @vset: requested charger output voltage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) * @iset: requested charger output current
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) * The AC charger will be turned on/off with the requested charge voltage and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) * current
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) static int abx500_chargalg_ac_en(struct abx500_chargalg *di, int enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) int vset, int iset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) static int abx500_chargalg_ex_ac_enable_toggle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) if (!di->ac_chg || !di->ac_chg->ops.enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) /* Select maximum of what both the charger and the battery supports */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) if (di->ac_chg->max_out_volt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) vset = min(vset, di->ac_chg->max_out_volt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) if (di->ac_chg->max_out_curr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) iset = min(iset, di->ac_chg->max_out_curr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) di->chg_info.ac_iset = iset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) di->chg_info.ac_vset = vset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) /* Enable external charger */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) if (enable && di->ac_chg->external &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) !abx500_chargalg_ex_ac_enable_toggle) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) blocking_notifier_call_chain(&charger_notifier_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) 0, di->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) abx500_chargalg_ex_ac_enable_toggle++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) return di->ac_chg->ops.enable(di->ac_chg, enable, vset, iset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) * abx500_chargalg_usb_en() - Turn on/off the USB charger
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) * @di: pointer to the abx500_chargalg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) * @enable: charger on/off
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) * @vset: requested charger output voltage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) * @iset: requested charger output current
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) * The USB charger will be turned on/off with the requested charge voltage and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) * current
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) static int abx500_chargalg_usb_en(struct abx500_chargalg *di, int enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) int vset, int iset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) if (!di->usb_chg || !di->usb_chg->ops.enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) /* Select maximum of what both the charger and the battery supports */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) if (di->usb_chg->max_out_volt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) vset = min(vset, di->usb_chg->max_out_volt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) if (di->usb_chg->max_out_curr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) iset = min(iset, di->usb_chg->max_out_curr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) di->chg_info.usb_iset = iset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) di->chg_info.usb_vset = vset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) return di->usb_chg->ops.enable(di->usb_chg, enable, vset, iset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) * abx500_chargalg_update_chg_curr() - Update charger current
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) * @di: pointer to the abx500_chargalg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) * @iset: requested charger output current
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) * The charger output current will be updated for the charger
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) * that is currently in use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) static int abx500_chargalg_update_chg_curr(struct abx500_chargalg *di,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) int iset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) /* Check if charger exists and update current if charging */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) if (di->ac_chg && di->ac_chg->ops.update_curr &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) di->chg_info.charger_type & AC_CHG) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) * Select maximum of what both the charger
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) * and the battery supports
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) if (di->ac_chg->max_out_curr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) iset = min(iset, di->ac_chg->max_out_curr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) di->chg_info.ac_iset = iset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) return di->ac_chg->ops.update_curr(di->ac_chg, iset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) } else if (di->usb_chg && di->usb_chg->ops.update_curr &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) di->chg_info.charger_type & USB_CHG) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) * Select maximum of what both the charger
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) * and the battery supports
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) if (di->usb_chg->max_out_curr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) iset = min(iset, di->usb_chg->max_out_curr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) di->chg_info.usb_iset = iset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) return di->usb_chg->ops.update_curr(di->usb_chg, iset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) * abx500_chargalg_stop_charging() - Stop charging
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) * @di: pointer to the abx500_chargalg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) * This function is called from any state where charging should be stopped.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) * All charging is disabled and all status parameters and timers are changed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) * accordingly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) static void abx500_chargalg_stop_charging(struct abx500_chargalg *di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) abx500_chargalg_ac_en(di, false, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) abx500_chargalg_usb_en(di, false, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) abx500_chargalg_stop_safety_timer(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) abx500_chargalg_stop_maintenance_timer(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) di->charge_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) di->maintenance_chg = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) cancel_delayed_work(&di->chargalg_wd_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) power_supply_changed(di->chargalg_psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) * abx500_chargalg_hold_charging() - Pauses charging
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) * @di: pointer to the abx500_chargalg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) * This function is called in the case where maintenance charging has been
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) * disabled and instead a battery voltage mode is entered to check when the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) * battery voltage has reached a certain recharge voltage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) static void abx500_chargalg_hold_charging(struct abx500_chargalg *di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) abx500_chargalg_ac_en(di, false, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) abx500_chargalg_usb_en(di, false, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) abx500_chargalg_stop_safety_timer(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) abx500_chargalg_stop_maintenance_timer(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) di->charge_status = POWER_SUPPLY_STATUS_CHARGING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) di->maintenance_chg = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) cancel_delayed_work(&di->chargalg_wd_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) power_supply_changed(di->chargalg_psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) * abx500_chargalg_start_charging() - Start the charger
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) * @di: pointer to the abx500_chargalg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) * @vset: requested charger output voltage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) * @iset: requested charger output current
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) * A charger will be enabled depending on the requested charger type that was
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) * detected previously.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) static void abx500_chargalg_start_charging(struct abx500_chargalg *di,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) int vset, int iset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) switch (di->chg_info.charger_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) case AC_CHG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) dev_dbg(di->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) "AC parameters: Vset %d, Ich %d\n", vset, iset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) abx500_chargalg_usb_en(di, false, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) abx500_chargalg_ac_en(di, true, vset, iset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) case USB_CHG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) dev_dbg(di->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) "USB parameters: Vset %d, Ich %d\n", vset, iset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) abx500_chargalg_ac_en(di, false, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) abx500_chargalg_usb_en(di, true, vset, iset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) dev_err(di->dev, "Unknown charger to charge from\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) * abx500_chargalg_check_temp() - Check battery temperature ranges
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) * @di: pointer to the abx500_chargalg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) * The battery temperature is checked against the predefined limits and the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) * charge state is changed accordingly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) static void abx500_chargalg_check_temp(struct abx500_chargalg *di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) if (di->batt_data.temp > (di->bm->temp_low + di->t_hyst_norm) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) di->batt_data.temp < (di->bm->temp_high - di->t_hyst_norm)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) /* Temp OK! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) di->events.btemp_underover = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) di->events.btemp_lowhigh = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) di->t_hyst_norm = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) di->t_hyst_lowhigh = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) if (((di->batt_data.temp >= di->bm->temp_high) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) (di->batt_data.temp <
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) (di->bm->temp_over - di->t_hyst_lowhigh))) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) ((di->batt_data.temp >
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) (di->bm->temp_under + di->t_hyst_lowhigh)) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) (di->batt_data.temp <= di->bm->temp_low))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) /* TEMP minor!!!!! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) di->events.btemp_underover = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) di->events.btemp_lowhigh = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) di->t_hyst_norm = di->bm->temp_hysteresis;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) di->t_hyst_lowhigh = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) } else if (di->batt_data.temp <= di->bm->temp_under ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) di->batt_data.temp >= di->bm->temp_over) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) /* TEMP major!!!!! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) di->events.btemp_underover = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) di->events.btemp_lowhigh = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) di->t_hyst_norm = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) di->t_hyst_lowhigh = di->bm->temp_hysteresis;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) /* Within hysteresis */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) dev_dbg(di->dev, "Within hysteresis limit temp: %d "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) "hyst_lowhigh %d, hyst normal %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) di->batt_data.temp, di->t_hyst_lowhigh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) di->t_hyst_norm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) * abx500_chargalg_check_charger_voltage() - Check charger voltage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) * @di: pointer to the abx500_chargalg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) * Charger voltage is checked against maximum limit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) static void abx500_chargalg_check_charger_voltage(struct abx500_chargalg *di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) if (di->chg_info.usb_volt > di->bm->chg_params->usb_volt_max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) di->chg_info.usb_chg_ok = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) di->chg_info.usb_chg_ok = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) if (di->chg_info.ac_volt > di->bm->chg_params->ac_volt_max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) di->chg_info.ac_chg_ok = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) di->chg_info.ac_chg_ok = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) * abx500_chargalg_end_of_charge() - Check if end-of-charge criteria is fulfilled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) * @di: pointer to the abx500_chargalg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) * End-of-charge criteria is fulfilled when the battery voltage is above a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) * certain limit and the battery current is below a certain limit for a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) * predefined number of consecutive seconds. If true, the battery is full
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) static void abx500_chargalg_end_of_charge(struct abx500_chargalg *di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) if (di->charge_status == POWER_SUPPLY_STATUS_CHARGING &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) di->charge_state == STATE_NORMAL &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) !di->maintenance_chg && (di->batt_data.volt >=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) di->bm->bat_type[di->bm->batt_id].termination_vol ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) di->events.usb_cv_active || di->events.ac_cv_active) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) di->batt_data.avg_curr <
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) di->bm->bat_type[di->bm->batt_id].termination_curr &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) di->batt_data.avg_curr > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) if (++di->eoc_cnt >= EOC_COND_CNT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) di->eoc_cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) di->charge_status = POWER_SUPPLY_STATUS_FULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) di->maintenance_chg = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) dev_dbg(di->dev, "EOC reached!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) power_supply_changed(di->chargalg_psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) dev_dbg(di->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) " EOC limit reached for the %d"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) " time, out of %d before EOC\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) di->eoc_cnt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) EOC_COND_CNT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) di->eoc_cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) static void init_maxim_chg_curr(struct abx500_chargalg *di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) di->ccm.original_iset =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) di->bm->bat_type[di->bm->batt_id].normal_cur_lvl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) di->ccm.current_iset =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) di->bm->bat_type[di->bm->batt_id].normal_cur_lvl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) di->ccm.test_delta_i = di->bm->maxi->charger_curr_step;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) di->ccm.max_current = di->bm->maxi->chg_curr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) di->ccm.condition_cnt = di->bm->maxi->wait_cycles;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) di->ccm.level = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) * abx500_chargalg_chg_curr_maxim - increases the charger current to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) * compensate for the system load
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) * @di pointer to the abx500_chargalg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) * This maximization function is used to raise the charger current to get the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) * battery current as close to the optimal value as possible. The battery
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) * current during charging is affected by the system load
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) static enum maxim_ret abx500_chargalg_chg_curr_maxim(struct abx500_chargalg *di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) int delta_i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) if (!di->bm->maxi->ena_maxi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) return MAXIM_RET_NOACTION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) delta_i = di->ccm.original_iset - di->batt_data.inst_curr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) if (di->events.vbus_collapsed) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) dev_dbg(di->dev, "Charger voltage has collapsed %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) di->ccm.wait_cnt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) if (di->ccm.wait_cnt == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) dev_dbg(di->dev, "lowering current\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) di->ccm.wait_cnt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) di->ccm.condition_cnt = di->bm->maxi->wait_cycles;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) di->ccm.max_current =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) di->ccm.current_iset - di->ccm.test_delta_i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) di->ccm.current_iset = di->ccm.max_current;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) di->ccm.level--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) return MAXIM_RET_CHANGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) dev_dbg(di->dev, "waiting\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) /* Let's go in here twice before lowering curr again */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) di->ccm.wait_cnt = (di->ccm.wait_cnt + 1) % 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) return MAXIM_RET_NOACTION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) di->ccm.wait_cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) if ((di->batt_data.inst_curr > di->ccm.original_iset)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) dev_dbg(di->dev, " Maximization Ibat (%dmA) too high"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) " (limit %dmA) (current iset: %dmA)!\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) di->batt_data.inst_curr, di->ccm.original_iset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) di->ccm.current_iset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) if (di->ccm.current_iset == di->ccm.original_iset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) return MAXIM_RET_NOACTION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) di->ccm.condition_cnt = di->bm->maxi->wait_cycles;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) di->ccm.current_iset = di->ccm.original_iset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) di->ccm.level = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) return MAXIM_RET_IBAT_TOO_HIGH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) if (delta_i > di->ccm.test_delta_i &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) (di->ccm.current_iset + di->ccm.test_delta_i) <
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) di->ccm.max_current) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) if (di->ccm.condition_cnt-- == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) /* Increse the iset with cco.test_delta_i */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) di->ccm.condition_cnt = di->bm->maxi->wait_cycles;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) di->ccm.current_iset += di->ccm.test_delta_i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) di->ccm.level++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) dev_dbg(di->dev, " Maximization needed, increase"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) " with %d mA to %dmA (Optimal ibat: %d)"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) " Level %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) di->ccm.test_delta_i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) di->ccm.current_iset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) di->ccm.original_iset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) di->ccm.level);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) return MAXIM_RET_CHANGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) return MAXIM_RET_NOACTION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) di->ccm.condition_cnt = di->bm->maxi->wait_cycles;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) return MAXIM_RET_NOACTION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) static void handle_maxim_chg_curr(struct abx500_chargalg *di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) enum maxim_ret ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) int result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) ret = abx500_chargalg_chg_curr_maxim(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) switch (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) case MAXIM_RET_CHANGE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) result = abx500_chargalg_update_chg_curr(di,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) di->ccm.current_iset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) if (result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) dev_err(di->dev, "failed to set chg curr\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) case MAXIM_RET_IBAT_TOO_HIGH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) result = abx500_chargalg_update_chg_curr(di,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) di->bm->bat_type[di->bm->batt_id].normal_cur_lvl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) if (result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) dev_err(di->dev, "failed to set chg curr\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) case MAXIM_RET_NOACTION:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) /* Do nothing..*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) static int abx500_chargalg_get_ext_psy_data(struct device *dev, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) struct power_supply *psy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) struct power_supply *ext = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) const char **supplicants = (const char **)ext->supplied_to;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) struct abx500_chargalg *di;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) union power_supply_propval ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) int j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) bool capacity_updated = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) psy = (struct power_supply *)data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) di = power_supply_get_drvdata(psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) /* For all psy where the driver name appears in any supplied_to */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) j = match_string(supplicants, ext->num_supplicants, psy->desc->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) if (j < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) * If external is not registering 'POWER_SUPPLY_PROP_CAPACITY' to its
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) * property because of handling that sysfs entry on its own, this is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) * the place to get the battery capacity.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) if (!power_supply_get_property(ext, POWER_SUPPLY_PROP_CAPACITY, &ret)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) di->batt_data.percent = ret.intval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) capacity_updated = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) /* Go through all properties for the psy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) for (j = 0; j < ext->desc->num_properties; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) enum power_supply_property prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) prop = ext->desc->properties[j];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) * Initialize chargers if not already done.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) * The ab8500_charger*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) if (!di->ac_chg &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) ext->desc->type == POWER_SUPPLY_TYPE_MAINS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) di->ac_chg = psy_to_ux500_charger(ext);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) else if (!di->usb_chg &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) ext->desc->type == POWER_SUPPLY_TYPE_USB)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) di->usb_chg = psy_to_ux500_charger(ext);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) if (power_supply_get_property(ext, prop, &ret))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) switch (prop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) case POWER_SUPPLY_PROP_PRESENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) switch (ext->desc->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) case POWER_SUPPLY_TYPE_BATTERY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) /* Battery present */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) if (ret.intval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) di->events.batt_rem = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) /* Battery removed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) di->events.batt_rem = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) case POWER_SUPPLY_TYPE_MAINS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) /* AC disconnected */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) if (!ret.intval &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) (di->chg_info.conn_chg & AC_CHG)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) di->chg_info.prev_conn_chg =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) di->chg_info.conn_chg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) di->chg_info.conn_chg &= ~AC_CHG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) /* AC connected */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) else if (ret.intval &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) !(di->chg_info.conn_chg & AC_CHG)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) di->chg_info.prev_conn_chg =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) di->chg_info.conn_chg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) di->chg_info.conn_chg |= AC_CHG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) case POWER_SUPPLY_TYPE_USB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) /* USB disconnected */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) if (!ret.intval &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) (di->chg_info.conn_chg & USB_CHG)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) di->chg_info.prev_conn_chg =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) di->chg_info.conn_chg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) di->chg_info.conn_chg &= ~USB_CHG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) /* USB connected */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) else if (ret.intval &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) !(di->chg_info.conn_chg & USB_CHG)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) di->chg_info.prev_conn_chg =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) di->chg_info.conn_chg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) di->chg_info.conn_chg |= USB_CHG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) case POWER_SUPPLY_PROP_ONLINE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) switch (ext->desc->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) case POWER_SUPPLY_TYPE_BATTERY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) case POWER_SUPPLY_TYPE_MAINS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) /* AC offline */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) if (!ret.intval &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) (di->chg_info.online_chg & AC_CHG)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) di->chg_info.prev_online_chg =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) di->chg_info.online_chg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) di->chg_info.online_chg &= ~AC_CHG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) /* AC online */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) else if (ret.intval &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) !(di->chg_info.online_chg & AC_CHG)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) di->chg_info.prev_online_chg =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) di->chg_info.online_chg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) di->chg_info.online_chg |= AC_CHG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) queue_delayed_work(di->chargalg_wq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) &di->chargalg_wd_work, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) case POWER_SUPPLY_TYPE_USB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) /* USB offline */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) if (!ret.intval &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) (di->chg_info.online_chg & USB_CHG)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) di->chg_info.prev_online_chg =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) di->chg_info.online_chg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) di->chg_info.online_chg &= ~USB_CHG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) /* USB online */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) else if (ret.intval &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) !(di->chg_info.online_chg & USB_CHG)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) di->chg_info.prev_online_chg =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) di->chg_info.online_chg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) di->chg_info.online_chg |= USB_CHG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) queue_delayed_work(di->chargalg_wq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) &di->chargalg_wd_work, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) case POWER_SUPPLY_PROP_HEALTH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) switch (ext->desc->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) case POWER_SUPPLY_TYPE_BATTERY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) case POWER_SUPPLY_TYPE_MAINS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) switch (ret.intval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) case POWER_SUPPLY_HEALTH_UNSPEC_FAILURE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) di->events.mainextchnotok = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) di->events.main_thermal_prot = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) di->events.main_ovv = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) di->events.ac_wd_expired = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) case POWER_SUPPLY_HEALTH_DEAD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) di->events.ac_wd_expired = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) di->events.mainextchnotok = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) di->events.main_ovv = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) di->events.main_thermal_prot = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) case POWER_SUPPLY_HEALTH_COLD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) case POWER_SUPPLY_HEALTH_OVERHEAT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) di->events.main_thermal_prot = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) di->events.mainextchnotok = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) di->events.main_ovv = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) di->events.ac_wd_expired = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) case POWER_SUPPLY_HEALTH_OVERVOLTAGE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) di->events.main_ovv = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) di->events.mainextchnotok = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) di->events.main_thermal_prot = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) di->events.ac_wd_expired = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) case POWER_SUPPLY_HEALTH_GOOD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) di->events.main_thermal_prot = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) di->events.mainextchnotok = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) di->events.main_ovv = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) di->events.ac_wd_expired = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) case POWER_SUPPLY_TYPE_USB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) switch (ret.intval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) case POWER_SUPPLY_HEALTH_UNSPEC_FAILURE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) di->events.usbchargernotok = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) di->events.usb_thermal_prot = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) di->events.vbus_ovv = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) di->events.usb_wd_expired = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) case POWER_SUPPLY_HEALTH_DEAD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) di->events.usb_wd_expired = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) di->events.usbchargernotok = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) di->events.usb_thermal_prot = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) di->events.vbus_ovv = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) case POWER_SUPPLY_HEALTH_COLD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) case POWER_SUPPLY_HEALTH_OVERHEAT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) di->events.usb_thermal_prot = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) di->events.usbchargernotok = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) di->events.vbus_ovv = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) di->events.usb_wd_expired = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) case POWER_SUPPLY_HEALTH_OVERVOLTAGE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) di->events.vbus_ovv = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) di->events.usbchargernotok = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) di->events.usb_thermal_prot = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) di->events.usb_wd_expired = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) case POWER_SUPPLY_HEALTH_GOOD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) di->events.usbchargernotok = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) di->events.usb_thermal_prot = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) di->events.vbus_ovv = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) di->events.usb_wd_expired = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) case POWER_SUPPLY_PROP_VOLTAGE_NOW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) switch (ext->desc->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) case POWER_SUPPLY_TYPE_BATTERY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) di->batt_data.volt = ret.intval / 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) case POWER_SUPPLY_TYPE_MAINS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) di->chg_info.ac_volt = ret.intval / 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) case POWER_SUPPLY_TYPE_USB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) di->chg_info.usb_volt = ret.intval / 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) case POWER_SUPPLY_PROP_VOLTAGE_AVG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) switch (ext->desc->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) case POWER_SUPPLY_TYPE_MAINS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) /* AVG is used to indicate when we are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) * in CV mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) if (ret.intval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) di->events.ac_cv_active = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) di->events.ac_cv_active = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) case POWER_SUPPLY_TYPE_USB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) /* AVG is used to indicate when we are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) * in CV mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) if (ret.intval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) di->events.usb_cv_active = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) di->events.usb_cv_active = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) case POWER_SUPPLY_PROP_TECHNOLOGY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) switch (ext->desc->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) case POWER_SUPPLY_TYPE_BATTERY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) if (ret.intval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) di->events.batt_unknown = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) di->events.batt_unknown = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) case POWER_SUPPLY_PROP_TEMP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) di->batt_data.temp = ret.intval / 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) case POWER_SUPPLY_PROP_CURRENT_NOW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) switch (ext->desc->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) case POWER_SUPPLY_TYPE_MAINS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) di->chg_info.ac_curr =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) ret.intval / 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) case POWER_SUPPLY_TYPE_USB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) di->chg_info.usb_curr =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) ret.intval / 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) case POWER_SUPPLY_TYPE_BATTERY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) di->batt_data.inst_curr = ret.intval / 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) case POWER_SUPPLY_PROP_CURRENT_AVG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) switch (ext->desc->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) case POWER_SUPPLY_TYPE_BATTERY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) di->batt_data.avg_curr = ret.intval / 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) case POWER_SUPPLY_TYPE_USB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) if (ret.intval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) di->events.vbus_collapsed = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) di->events.vbus_collapsed = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) case POWER_SUPPLY_PROP_CAPACITY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) if (!capacity_updated)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) di->batt_data.percent = ret.intval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) * abx500_chargalg_external_power_changed() - callback for power supply changes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) * @psy: pointer to the structure power_supply
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) * This function is the entry point of the pointer external_power_changed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) * of the structure power_supply.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) * This function gets executed when there is a change in any external power
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) * supply that this driver needs to be notified of.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) static void abx500_chargalg_external_power_changed(struct power_supply *psy)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) struct abx500_chargalg *di = power_supply_get_drvdata(psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) * Trigger execution of the algorithm instantly and read
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) * all power_supply properties there instead
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) queue_work(di->chargalg_wq, &di->chargalg_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) * abx500_chargalg_algorithm() - Main function for the algorithm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) * @di: pointer to the abx500_chargalg structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) * This is the main control function for the charging algorithm.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) * It is called periodically or when something happens that will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) * trigger a state change
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) static void abx500_chargalg_algorithm(struct abx500_chargalg *di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) int charger_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) int curr_step_lvl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) /* Collect data from all power_supply class devices */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) class_for_each_device(power_supply_class, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) di->chargalg_psy, abx500_chargalg_get_ext_psy_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) abx500_chargalg_end_of_charge(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) abx500_chargalg_check_temp(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) abx500_chargalg_check_charger_voltage(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) charger_status = abx500_chargalg_check_charger_connection(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) abx500_chargalg_check_current_step_status(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) if (is_ab8500(di->parent)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) ret = abx500_chargalg_check_charger_enable(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) dev_err(di->dev, "Checking charger is enabled error"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) ": Returned Value %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) * First check if we have a charger connected.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) * Also we don't allow charging of unknown batteries if configured
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) * this way
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) if (!charger_status ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) (di->events.batt_unknown && !di->bm->chg_unknown_bat)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) if (di->charge_state != STATE_HANDHELD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) di->events.safety_timer_expired = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) abx500_chargalg_state_to(di, STATE_HANDHELD_INIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) /* If suspended, we should not continue checking the flags */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) else if (di->charge_state == STATE_SUSPENDED_INIT ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) di->charge_state == STATE_SUSPENDED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) /* We don't do anything here, just don,t continue */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) /* Safety timer expiration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) else if (di->events.safety_timer_expired) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) if (di->charge_state != STATE_SAFETY_TIMER_EXPIRED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) abx500_chargalg_state_to(di,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) STATE_SAFETY_TIMER_EXPIRED_INIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) * Check if any interrupts has occured
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) * that will prevent us from charging
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) /* Battery removed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) else if (di->events.batt_rem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) if (di->charge_state != STATE_BATT_REMOVED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) abx500_chargalg_state_to(di, STATE_BATT_REMOVED_INIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) /* Main or USB charger not ok. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) else if (di->events.mainextchnotok || di->events.usbchargernotok) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) * If vbus_collapsed is set, we have to lower the charger
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) * current, which is done in the normal state below
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) if (di->charge_state != STATE_CHG_NOT_OK &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) !di->events.vbus_collapsed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) abx500_chargalg_state_to(di, STATE_CHG_NOT_OK_INIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) /* VBUS, Main or VBAT OVV. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) else if (di->events.vbus_ovv ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) di->events.main_ovv ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) di->events.batt_ovv ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) !di->chg_info.usb_chg_ok ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) !di->chg_info.ac_chg_ok) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) if (di->charge_state != STATE_OVV_PROTECT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) abx500_chargalg_state_to(di, STATE_OVV_PROTECT_INIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) /* USB Thermal, stop charging */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) else if (di->events.main_thermal_prot ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) di->events.usb_thermal_prot) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) if (di->charge_state != STATE_HW_TEMP_PROTECT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) abx500_chargalg_state_to(di,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) STATE_HW_TEMP_PROTECT_INIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) /* Battery temp over/under */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) else if (di->events.btemp_underover) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) if (di->charge_state != STATE_TEMP_UNDEROVER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) abx500_chargalg_state_to(di,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) STATE_TEMP_UNDEROVER_INIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) /* Watchdog expired */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) else if (di->events.ac_wd_expired ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) di->events.usb_wd_expired) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) if (di->charge_state != STATE_WD_EXPIRED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) abx500_chargalg_state_to(di, STATE_WD_EXPIRED_INIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) /* Battery temp high/low */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) else if (di->events.btemp_lowhigh) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) if (di->charge_state != STATE_TEMP_LOWHIGH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) abx500_chargalg_state_to(di, STATE_TEMP_LOWHIGH_INIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) dev_dbg(di->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) "[CHARGALG] Vb %d Ib_avg %d Ib_inst %d Tb %d Cap %d Maint %d "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) "State %s Active_chg %d Chg_status %d AC %d USB %d "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) "AC_online %d USB_online %d AC_CV %d USB_CV %d AC_I %d "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) "USB_I %d AC_Vset %d AC_Iset %d USB_Vset %d USB_Iset %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) di->batt_data.volt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) di->batt_data.avg_curr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) di->batt_data.inst_curr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) di->batt_data.temp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) di->batt_data.percent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) di->maintenance_chg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) states[di->charge_state],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) di->chg_info.charger_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) di->charge_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) di->chg_info.conn_chg & AC_CHG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) di->chg_info.conn_chg & USB_CHG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) di->chg_info.online_chg & AC_CHG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) di->chg_info.online_chg & USB_CHG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) di->events.ac_cv_active,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) di->events.usb_cv_active,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) di->chg_info.ac_curr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) di->chg_info.usb_curr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) di->chg_info.ac_vset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) di->chg_info.ac_iset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) di->chg_info.usb_vset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) di->chg_info.usb_iset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) switch (di->charge_state) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) case STATE_HANDHELD_INIT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) abx500_chargalg_stop_charging(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) di->charge_status = POWER_SUPPLY_STATUS_DISCHARGING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) abx500_chargalg_state_to(di, STATE_HANDHELD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) case STATE_HANDHELD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) case STATE_SUSPENDED_INIT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) if (di->susp_status.ac_suspended)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) abx500_chargalg_ac_en(di, false, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) if (di->susp_status.usb_suspended)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) abx500_chargalg_usb_en(di, false, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) abx500_chargalg_stop_safety_timer(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) abx500_chargalg_stop_maintenance_timer(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) di->charge_status = POWER_SUPPLY_STATUS_NOT_CHARGING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) di->maintenance_chg = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) abx500_chargalg_state_to(di, STATE_SUSPENDED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) power_supply_changed(di->chargalg_psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) case STATE_SUSPENDED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) /* CHARGING is suspended */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) case STATE_BATT_REMOVED_INIT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) abx500_chargalg_stop_charging(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) abx500_chargalg_state_to(di, STATE_BATT_REMOVED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) case STATE_BATT_REMOVED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) if (!di->events.batt_rem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) abx500_chargalg_state_to(di, STATE_NORMAL_INIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) case STATE_HW_TEMP_PROTECT_INIT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) abx500_chargalg_stop_charging(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) abx500_chargalg_state_to(di, STATE_HW_TEMP_PROTECT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) case STATE_HW_TEMP_PROTECT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) if (!di->events.main_thermal_prot &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) !di->events.usb_thermal_prot)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) abx500_chargalg_state_to(di, STATE_NORMAL_INIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) case STATE_OVV_PROTECT_INIT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) abx500_chargalg_stop_charging(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) abx500_chargalg_state_to(di, STATE_OVV_PROTECT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) case STATE_OVV_PROTECT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) if (!di->events.vbus_ovv &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) !di->events.main_ovv &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) !di->events.batt_ovv &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) di->chg_info.usb_chg_ok &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) di->chg_info.ac_chg_ok)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) abx500_chargalg_state_to(di, STATE_NORMAL_INIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) case STATE_CHG_NOT_OK_INIT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) abx500_chargalg_stop_charging(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) abx500_chargalg_state_to(di, STATE_CHG_NOT_OK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) case STATE_CHG_NOT_OK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) if (!di->events.mainextchnotok &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) !di->events.usbchargernotok)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) abx500_chargalg_state_to(di, STATE_NORMAL_INIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) case STATE_SAFETY_TIMER_EXPIRED_INIT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) abx500_chargalg_stop_charging(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) abx500_chargalg_state_to(di, STATE_SAFETY_TIMER_EXPIRED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) case STATE_SAFETY_TIMER_EXPIRED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) /* We exit this state when charger is removed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) case STATE_NORMAL_INIT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) if (di->curr_status.curr_step == CHARGALG_CURR_STEP_LOW)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) abx500_chargalg_stop_charging(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) curr_step_lvl = di->bm->bat_type[
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) di->bm->batt_id].normal_cur_lvl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) * di->curr_status.curr_step
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) / CHARGALG_CURR_STEP_HIGH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) abx500_chargalg_start_charging(di,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) di->bm->bat_type[di->bm->batt_id]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) .normal_vol_lvl, curr_step_lvl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) abx500_chargalg_state_to(di, STATE_NORMAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) abx500_chargalg_start_safety_timer(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) abx500_chargalg_stop_maintenance_timer(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) init_maxim_chg_curr(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) di->charge_status = POWER_SUPPLY_STATUS_CHARGING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) di->eoc_cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) di->maintenance_chg = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) power_supply_changed(di->chargalg_psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) case STATE_NORMAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) handle_maxim_chg_curr(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) if (di->charge_status == POWER_SUPPLY_STATUS_FULL &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) di->maintenance_chg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) if (di->bm->no_maintenance)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) abx500_chargalg_state_to(di,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) STATE_WAIT_FOR_RECHARGE_INIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) abx500_chargalg_state_to(di,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) STATE_MAINTENANCE_A_INIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) /* This state will be used when the maintenance state is disabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) case STATE_WAIT_FOR_RECHARGE_INIT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) abx500_chargalg_hold_charging(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) abx500_chargalg_state_to(di, STATE_WAIT_FOR_RECHARGE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) case STATE_WAIT_FOR_RECHARGE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) if (di->batt_data.percent <=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) di->bm->bat_type[di->bm->batt_id].
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) recharge_cap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) abx500_chargalg_state_to(di, STATE_NORMAL_INIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) case STATE_MAINTENANCE_A_INIT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) abx500_chargalg_stop_safety_timer(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) abx500_chargalg_start_maintenance_timer(di,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) di->bm->bat_type[
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) di->bm->batt_id].maint_a_chg_timer_h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) abx500_chargalg_start_charging(di,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) di->bm->bat_type[
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) di->bm->batt_id].maint_a_vol_lvl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) di->bm->bat_type[
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) di->bm->batt_id].maint_a_cur_lvl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) abx500_chargalg_state_to(di, STATE_MAINTENANCE_A);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) power_supply_changed(di->chargalg_psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) case STATE_MAINTENANCE_A:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) if (di->events.maintenance_timer_expired) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) abx500_chargalg_stop_maintenance_timer(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) abx500_chargalg_state_to(di, STATE_MAINTENANCE_B_INIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) case STATE_MAINTENANCE_B_INIT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) abx500_chargalg_start_maintenance_timer(di,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) di->bm->bat_type[
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) di->bm->batt_id].maint_b_chg_timer_h);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) abx500_chargalg_start_charging(di,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) di->bm->bat_type[
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) di->bm->batt_id].maint_b_vol_lvl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) di->bm->bat_type[
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) di->bm->batt_id].maint_b_cur_lvl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) abx500_chargalg_state_to(di, STATE_MAINTENANCE_B);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580) power_supply_changed(di->chargalg_psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) case STATE_MAINTENANCE_B:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) if (di->events.maintenance_timer_expired) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) abx500_chargalg_stop_maintenance_timer(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) abx500_chargalg_state_to(di, STATE_NORMAL_INIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) case STATE_TEMP_LOWHIGH_INIT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) abx500_chargalg_start_charging(di,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) di->bm->bat_type[
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) di->bm->batt_id].low_high_vol_lvl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) di->bm->bat_type[
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) di->bm->batt_id].low_high_cur_lvl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) abx500_chargalg_stop_maintenance_timer(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) di->charge_status = POWER_SUPPLY_STATUS_CHARGING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) abx500_chargalg_state_to(di, STATE_TEMP_LOWHIGH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) power_supply_changed(di->chargalg_psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) case STATE_TEMP_LOWHIGH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) if (!di->events.btemp_lowhigh)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) abx500_chargalg_state_to(di, STATE_NORMAL_INIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) case STATE_WD_EXPIRED_INIT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) abx500_chargalg_stop_charging(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) abx500_chargalg_state_to(di, STATE_WD_EXPIRED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) case STATE_WD_EXPIRED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) if (!di->events.ac_wd_expired &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) !di->events.usb_wd_expired)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) abx500_chargalg_state_to(di, STATE_NORMAL_INIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) case STATE_TEMP_UNDEROVER_INIT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) abx500_chargalg_stop_charging(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) abx500_chargalg_state_to(di, STATE_TEMP_UNDEROVER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) case STATE_TEMP_UNDEROVER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) if (!di->events.btemp_underover)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) abx500_chargalg_state_to(di, STATE_NORMAL_INIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) /* Start charging directly if the new state is a charge state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) if (di->charge_state == STATE_NORMAL_INIT ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) di->charge_state == STATE_MAINTENANCE_A_INIT ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) di->charge_state == STATE_MAINTENANCE_B_INIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) queue_work(di->chargalg_wq, &di->chargalg_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) * abx500_chargalg_periodic_work() - Periodic work for the algorithm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) * @work: pointer to the work_struct structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) * Work queue function for the charging algorithm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) static void abx500_chargalg_periodic_work(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) struct abx500_chargalg *di = container_of(work,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) struct abx500_chargalg, chargalg_periodic_work.work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) abx500_chargalg_algorithm(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) * If a charger is connected then the battery has to be monitored
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) * frequently, else the work can be delayed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) if (di->chg_info.conn_chg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654) queue_delayed_work(di->chargalg_wq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) &di->chargalg_periodic_work,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) di->bm->interval_charging * HZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) queue_delayed_work(di->chargalg_wq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) &di->chargalg_periodic_work,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) di->bm->interval_not_charging * HZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) * abx500_chargalg_wd_work() - periodic work to kick the charger watchdog
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) * @work: pointer to the work_struct structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) * Work queue function for kicking the charger watchdog
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) static void abx500_chargalg_wd_work(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) struct abx500_chargalg *di = container_of(work,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) struct abx500_chargalg, chargalg_wd_work.work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) dev_dbg(di->dev, "abx500_chargalg_wd_work\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) ret = abx500_chargalg_kick_watchdog(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) dev_err(di->dev, "failed to kick watchdog\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) queue_delayed_work(di->chargalg_wq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) &di->chargalg_wd_work, CHG_WD_INTERVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) * abx500_chargalg_work() - Work to run the charging algorithm instantly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) * @work: pointer to the work_struct structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) * Work queue function for calling the charging algorithm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) static void abx500_chargalg_work(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693) struct abx500_chargalg *di = container_of(work,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) struct abx500_chargalg, chargalg_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) abx500_chargalg_algorithm(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) * abx500_chargalg_get_property() - get the chargalg properties
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) * @psy: pointer to the power_supply structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) * @psp: pointer to the power_supply_property structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) * @val: pointer to the power_supply_propval union
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) * This function gets called when an application tries to get the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) * chargalg properties by reading the sysfs files.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) * status: charging/discharging/full/unknown
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) * health: health of the battery
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) * Returns error code in case of failure else 0 on success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) static int abx500_chargalg_get_property(struct power_supply *psy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) enum power_supply_property psp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) union power_supply_propval *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) struct abx500_chargalg *di = power_supply_get_drvdata(psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) switch (psp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) case POWER_SUPPLY_PROP_STATUS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) val->intval = di->charge_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) case POWER_SUPPLY_PROP_HEALTH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) if (di->events.batt_ovv) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) } else if (di->events.btemp_underover) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) if (di->batt_data.temp <= di->bm->temp_under)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) val->intval = POWER_SUPPLY_HEALTH_COLD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) } else if (di->charge_state == STATE_SAFETY_TIMER_EXPIRED ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) di->charge_state == STATE_SAFETY_TIMER_EXPIRED_INIT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) val->intval = POWER_SUPPLY_HEALTH_GOOD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) /* Exposure to the sysfs interface */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) static ssize_t abx500_chargalg_curr_step_show(struct abx500_chargalg *di,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) return sprintf(buf, "%d\n", di->curr_status.curr_step);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) static ssize_t abx500_chargalg_curr_step_store(struct abx500_chargalg *di,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) const char *buf, size_t length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) long int param;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756) ret = kstrtol(buf, 10, ¶m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) di->curr_status.curr_step = param;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761) if (di->curr_status.curr_step >= CHARGALG_CURR_STEP_LOW &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) di->curr_status.curr_step <= CHARGALG_CURR_STEP_HIGH) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) di->curr_status.curr_step_change = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) queue_work(di->chargalg_wq, &di->chargalg_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766) dev_info(di->dev, "Wrong current step\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) "Enter 0. Disable AC/USB Charging\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) "1--100. Set AC/USB charging current step\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) "100. Enable AC/USB Charging\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) return strlen(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) static ssize_t abx500_chargalg_en_show(struct abx500_chargalg *di,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) return sprintf(buf, "%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) di->susp_status.ac_suspended &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) di->susp_status.usb_suspended);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) static ssize_t abx500_chargalg_en_store(struct abx500_chargalg *di,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) const char *buf, size_t length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) long int param;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) int ac_usb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) ret = kstrtol(buf, 10, ¶m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) ac_usb = param;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) switch (ac_usb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) /* Disable charging */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) di->susp_status.ac_suspended = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) di->susp_status.usb_suspended = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800) di->susp_status.suspended_change = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) /* Trigger a state change */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) queue_work(di->chargalg_wq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) &di->chargalg_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) /* Enable AC Charging */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) di->susp_status.ac_suspended = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) di->susp_status.suspended_change = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809) /* Trigger a state change */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) queue_work(di->chargalg_wq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) &di->chargalg_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) /* Enable USB charging */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) di->susp_status.usb_suspended = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) di->susp_status.suspended_change = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817) /* Trigger a state change */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) queue_work(di->chargalg_wq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) &di->chargalg_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) dev_info(di->dev, "Wrong input\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823) "Enter 0. Disable AC/USB Charging\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) "1. Enable AC charging\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825) "2. Enable USB Charging\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) return strlen(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) static struct abx500_chargalg_sysfs_entry abx500_chargalg_en_charger =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) __ATTR(chargalg, 0644, abx500_chargalg_en_show,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) abx500_chargalg_en_store);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) static struct abx500_chargalg_sysfs_entry abx500_chargalg_curr_step =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835) __ATTR(chargalg_curr_step, 0644, abx500_chargalg_curr_step_show,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) abx500_chargalg_curr_step_store);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) static ssize_t abx500_chargalg_sysfs_show(struct kobject *kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) struct attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) struct abx500_chargalg_sysfs_entry *entry = container_of(attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842) struct abx500_chargalg_sysfs_entry, attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) struct abx500_chargalg *di = container_of(kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) struct abx500_chargalg, chargalg_kobject);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847) if (!entry->show)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) return entry->show(di, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853) static ssize_t abx500_chargalg_sysfs_charger(struct kobject *kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) struct attribute *attr, const char *buf, size_t length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856) struct abx500_chargalg_sysfs_entry *entry = container_of(attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) struct abx500_chargalg_sysfs_entry, attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) struct abx500_chargalg *di = container_of(kobj,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) struct abx500_chargalg, chargalg_kobject);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) if (!entry->store)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865) return entry->store(di, buf, length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868) static struct attribute *abx500_chargalg_chg[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) &abx500_chargalg_en_charger.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) &abx500_chargalg_curr_step.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874) static const struct sysfs_ops abx500_chargalg_sysfs_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) .show = abx500_chargalg_sysfs_show,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) .store = abx500_chargalg_sysfs_charger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) static struct kobj_type abx500_chargalg_ktype = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) .sysfs_ops = &abx500_chargalg_sysfs_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881) .default_attrs = abx500_chargalg_chg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) * abx500_chargalg_sysfs_exit() - de-init of sysfs entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) * @di: pointer to the struct abx500_chargalg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) * This function removes the entry in sysfs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) static void abx500_chargalg_sysfs_exit(struct abx500_chargalg *di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) kobject_del(&di->chargalg_kobject);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) * abx500_chargalg_sysfs_init() - init of sysfs entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) * @di: pointer to the struct abx500_chargalg
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) * This function adds an entry in sysfs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) * Returns error code in case of failure else 0(on success)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) static int abx500_chargalg_sysfs_init(struct abx500_chargalg *di)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) ret = kobject_init_and_add(&di->chargalg_kobject,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907) &abx500_chargalg_ktype,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) NULL, "abx500_chargalg");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910) dev_err(di->dev, "failed to create sysfs entry\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914) /* Exposure to the sysfs interface <<END>> */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) #if defined(CONFIG_PM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) static int abx500_chargalg_resume(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919) struct abx500_chargalg *di = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) /* Kick charger watchdog if charging (any charger online) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) if (di->chg_info.online_chg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923) queue_delayed_work(di->chargalg_wq, &di->chargalg_wd_work, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) * Run the charging algorithm directly to be sure we don't
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927) * do it too seldom
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929) queue_delayed_work(di->chargalg_wq, &di->chargalg_periodic_work, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934) static int abx500_chargalg_suspend(struct platform_device *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) pm_message_t state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) struct abx500_chargalg *di = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) if (di->chg_info.online_chg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940) cancel_delayed_work_sync(&di->chargalg_wd_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) cancel_delayed_work_sync(&di->chargalg_periodic_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) #define abx500_chargalg_suspend NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) #define abx500_chargalg_resume NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) static int abx500_chargalg_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) struct abx500_chargalg *di = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) /* sysfs interface to enable/disbale charging from user space */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956) abx500_chargalg_sysfs_exit(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) hrtimer_cancel(&di->safety_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959) hrtimer_cancel(&di->maintenance_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) cancel_delayed_work_sync(&di->chargalg_periodic_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) cancel_delayed_work_sync(&di->chargalg_wd_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) cancel_work_sync(&di->chargalg_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) /* Delete the work queue */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) destroy_workqueue(di->chargalg_wq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968) power_supply_unregister(di->chargalg_psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973) static char *supply_interface[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974) "ab8500_fg",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) static const struct power_supply_desc abx500_chargalg_desc = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978) .name = "abx500_chargalg",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979) .type = POWER_SUPPLY_TYPE_BATTERY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) .properties = abx500_chargalg_props,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981) .num_properties = ARRAY_SIZE(abx500_chargalg_props),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982) .get_property = abx500_chargalg_get_property,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983) .external_power_changed = abx500_chargalg_external_power_changed,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986) static int abx500_chargalg_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) struct device_node *np = pdev->dev.of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) struct abx500_bm_data *plat = pdev->dev.platform_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990) struct power_supply_config psy_cfg = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991) struct abx500_chargalg *di;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1995) if (!di) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1996) dev_err(&pdev->dev, "%s no mem for ab8500_chargalg\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1997) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1998) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1999)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2000) if (!plat) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2001) dev_err(&pdev->dev, "no battery management data supplied\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2002) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2003) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2004) di->bm = plat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2005)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2006) if (np) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2007) ret = ab8500_bm_of_probe(&pdev->dev, np, di->bm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2008) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2009) dev_err(&pdev->dev, "failed to get battery information\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2010) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2011) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2012) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2014) /* get device struct and parent */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2015) di->dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2016) di->parent = dev_get_drvdata(pdev->dev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2017)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2018) psy_cfg.supplied_to = supply_interface;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2019) psy_cfg.num_supplicants = ARRAY_SIZE(supply_interface);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2020) psy_cfg.drv_data = di;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2022) /* Initilialize safety timer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2023) hrtimer_init(&di->safety_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2024) di->safety_timer.function = abx500_chargalg_safety_timer_expired;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2026) /* Initilialize maintenance timer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2027) hrtimer_init(&di->maintenance_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2028) di->maintenance_timer.function =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2029) abx500_chargalg_maintenance_timer_expired;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2030)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2031) /* Create a work queue for the chargalg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2032) di->chargalg_wq = alloc_ordered_workqueue("abx500_chargalg_wq",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2033) WQ_MEM_RECLAIM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2034) if (di->chargalg_wq == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2035) dev_err(di->dev, "failed to create work queue\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2036) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2037) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2039) /* Init work for chargalg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2040) INIT_DEFERRABLE_WORK(&di->chargalg_periodic_work,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2041) abx500_chargalg_periodic_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2042) INIT_DEFERRABLE_WORK(&di->chargalg_wd_work,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2043) abx500_chargalg_wd_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2044)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2045) /* Init work for chargalg */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2046) INIT_WORK(&di->chargalg_work, abx500_chargalg_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2047)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2048) /* To detect charger at startup */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2049) di->chg_info.prev_conn_chg = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2050)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2051) /* Register chargalg power supply class */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2052) di->chargalg_psy = power_supply_register(di->dev, &abx500_chargalg_desc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2053) &psy_cfg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2054) if (IS_ERR(di->chargalg_psy)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2055) dev_err(di->dev, "failed to register chargalg psy\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2056) ret = PTR_ERR(di->chargalg_psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2057) goto free_chargalg_wq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2058) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2059)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2060) platform_set_drvdata(pdev, di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2061)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2062) /* sysfs interface to enable/disable charging from user space */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2063) ret = abx500_chargalg_sysfs_init(di);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2064) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2065) dev_err(di->dev, "failed to create sysfs entry\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2066) goto free_psy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2067) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2068) di->curr_status.curr_step = CHARGALG_CURR_STEP_HIGH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2069)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2070) /* Run the charging algorithm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2071) queue_delayed_work(di->chargalg_wq, &di->chargalg_periodic_work, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2072)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2073) dev_info(di->dev, "probe success\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2074) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2075)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2076) free_psy:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2077) power_supply_unregister(di->chargalg_psy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2078) free_chargalg_wq:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2079) destroy_workqueue(di->chargalg_wq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2080) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2081) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2082)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2083) static const struct of_device_id ab8500_chargalg_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2084) { .compatible = "stericsson,ab8500-chargalg", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2085) { },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2086) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2087)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2088) static struct platform_driver abx500_chargalg_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2089) .probe = abx500_chargalg_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2090) .remove = abx500_chargalg_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2091) .suspend = abx500_chargalg_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2092) .resume = abx500_chargalg_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2093) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2094) .name = "ab8500-chargalg",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2095) .of_match_table = ab8500_chargalg_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2096) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2097) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2098)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2099) module_platform_driver(abx500_chargalg_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2101) MODULE_LICENSE("GPL v2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2102) MODULE_AUTHOR("Johan Palsson, Karl Komierowski");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2103) MODULE_ALIAS("platform:abx500-chargalg");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2104) MODULE_DESCRIPTION("abx500 battery charging algorithm");