mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-09 05:39:54 -04:00
p938x_charger: Reduce dc current if battery too hot
Reduce the dc current by 100mA if the battery reports that it has entered a hot temp zone. Charging is more efficient if the battery is cool. Each time the temp zone is re-entered the current will be reduced. When the temp zone is exited a timer of 5 minutes will start, and if the high zone is not entered again the max current will be restored by triggering dc AICL to rerun. Change-Id: I5b9ac02410e33a729bcade957d9a5676376a0cb6 Signed-off-by: Ryan Lattrel <ryanl@motorola.com> Reviewed-on: https://gerrit.mot.com/1499273 SLTApproved: Slta Waiver SME-Granted: SME Approvals Granted Tested-by: Jira Key Reviewed-by: Cesar Augusto Marcelino dos Santos <cmsantos@motorola.com> Reviewed-by: Ling Jin <lingjin@motorola.com> Submit-Approved: Jira Key
This commit is contained in:
parent
60e7620e60
commit
38c2b1b771
1 changed files with 110 additions and 14 deletions
|
|
@ -156,6 +156,10 @@
|
|||
#define MAX_CHIP_VERS 0x9389
|
||||
#define CHIP_VENDOR "idt"
|
||||
|
||||
#define IDC_THERMAL_RESTORE_TIME 300000 /* 5 minutes */
|
||||
#define IDC_THERMAL_BACKOFF_MA 100
|
||||
#define IDC_THERMAL_MIN_CURRENT 400
|
||||
|
||||
#define DETACH_ON_READ_FAILURE
|
||||
|
||||
#define p938x_err(chip, fmt, ...) \
|
||||
|
|
@ -279,6 +283,7 @@ struct p938x_charger {
|
|||
struct delayed_work heartbeat_work;
|
||||
struct delayed_work tx_mode_work;
|
||||
struct delayed_work removal_work;
|
||||
struct delayed_work restore_idc_work;
|
||||
int heartbeat_count;
|
||||
|
||||
u32 peek_poke_address;
|
||||
|
|
@ -287,6 +292,9 @@ struct p938x_charger {
|
|||
struct power_supply *usb_psy;
|
||||
struct power_supply *wls_psy;
|
||||
struct power_supply *dc_psy;
|
||||
struct power_supply *batt_psy;
|
||||
|
||||
bool batt_hot;
|
||||
|
||||
char fw_name[NAME_MAX];
|
||||
int program_fw_stat;
|
||||
|
|
@ -335,6 +343,7 @@ static char *pm_wls_supplied_to[] = {
|
|||
/* Get notifications from supplies */
|
||||
static char *pm_wls_supplied_from[] = {
|
||||
"usb",
|
||||
"battery",
|
||||
};
|
||||
|
||||
static inline int p938x_is_chip_on(struct p938x_charger *chip)
|
||||
|
|
@ -635,11 +644,16 @@ static void p938x_toggle_power(struct p938x_charger *chip, int extra_delay_ms)
|
|||
msleep(100);
|
||||
}
|
||||
|
||||
static int p938x_get_dc_now_icl_ma(struct p938x_charger *chip, unsigned int *idc);
|
||||
static int p938x_set_dc_now_icl_ma(struct p938x_charger *chip, unsigned int idc);
|
||||
|
||||
static int p938x_update_supplies_status(struct p938x_charger *chip)
|
||||
{
|
||||
int rc;
|
||||
union power_supply_propval prop = {0,};
|
||||
int wired_connection;
|
||||
unsigned int dc_current_now;
|
||||
unsigned int dc_current_new;
|
||||
|
||||
if (!chip->usb_psy)
|
||||
chip->usb_psy = power_supply_get_by_name("usb");
|
||||
|
|
@ -672,6 +686,47 @@ static int p938x_update_supplies_status(struct p938x_charger *chip)
|
|||
gpio_set_value(chip->wchg_en_n.gpio, 0);
|
||||
}
|
||||
|
||||
if (!chip->batt_psy)
|
||||
chip->batt_psy = power_supply_get_by_name("battery");
|
||||
if (!chip->batt_psy) {
|
||||
pr_debug("batt psy not found\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
rc = power_supply_get_property(chip->batt_psy,
|
||||
POWER_SUPPLY_PROP_HOT_TEMP, &prop);
|
||||
if (rc) {
|
||||
p938x_err(chip, "Couldn't read batt temp zone prop, rc=%d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (!chip->batt_hot && prop.intval) {
|
||||
/* If the battery is too hot, lower the current
|
||||
* setting to try to keep us in optimal temp zone
|
||||
*/
|
||||
cancel_delayed_work(&chip->restore_idc_work);
|
||||
chip->batt_hot = 1;
|
||||
|
||||
rc = p938x_get_dc_now_icl_ma(chip, &dc_current_now);
|
||||
if (rc) {
|
||||
p938x_err(chip, "Couldn't read dc current, rc=%d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
dc_current_new = dc_current_now - IDC_THERMAL_BACKOFF_MA;
|
||||
if (dc_current_new < IDC_THERMAL_MIN_CURRENT)
|
||||
dc_current_new = IDC_THERMAL_MIN_CURRENT;
|
||||
|
||||
p938x_set_dc_now_icl_ma(chip, dc_current_new);
|
||||
p938x_dbg(chip, PR_IMPORTANT, "Reduced dc current to %u mA due to hot battery\n",
|
||||
dc_current_new);
|
||||
} else if (chip->batt_hot && !prop.intval) {
|
||||
/* Set work to restore original current settings */
|
||||
chip->batt_hot = 0;
|
||||
cancel_delayed_work(&chip->restore_idc_work);
|
||||
schedule_delayed_work(&chip->restore_idc_work,
|
||||
msecs_to_jiffies(IDC_THERMAL_RESTORE_TIME));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -867,6 +922,60 @@ static int p938x_set_dc_max_icl_ma(struct p938x_charger *chip, unsigned int idc)
|
|||
val);
|
||||
}
|
||||
|
||||
static int p938x_set_dc_now_icl_ma(struct p938x_charger *chip, unsigned int idc)
|
||||
{
|
||||
union power_supply_propval val;
|
||||
|
||||
p938x_dbg(chip, PR_MOTO, "Setting IDC to %u mA\n", idc);
|
||||
|
||||
idc *= 1000; /* Convert to uA */
|
||||
val.intval = idc;
|
||||
|
||||
return p938x_set_dc_psp_prop(chip,
|
||||
POWER_SUPPLY_PROP_CURRENT_NOW,
|
||||
val);
|
||||
}
|
||||
|
||||
static int p938x_get_dc_now_icl_ma(struct p938x_charger *chip, unsigned int *idc)
|
||||
{
|
||||
union power_supply_propval prop = {0,};
|
||||
int rc = 1;
|
||||
|
||||
if (chip->dc_psy) {
|
||||
rc = power_supply_get_property(chip->dc_psy,
|
||||
POWER_SUPPLY_PROP_CURRENT_NOW, &prop);
|
||||
if (rc) {
|
||||
p938x_err(chip, "Couldn't read batt temp zone prop, rc=%d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
*idc = prop.intval / 1000;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int p938x_set_dc_aicl_rerun(struct p938x_charger *chip)
|
||||
{
|
||||
union power_supply_propval val;
|
||||
|
||||
/* unused */
|
||||
val.intval = 1;
|
||||
|
||||
return p938x_set_dc_psp_prop(chip,
|
||||
POWER_SUPPLY_PROP_RERUN_AICL,
|
||||
val);
|
||||
}
|
||||
|
||||
static void p938x_restore_idc_work(struct work_struct *work)
|
||||
{
|
||||
struct p938x_charger *chip = container_of(work,
|
||||
struct p938x_charger, restore_idc_work.work);
|
||||
|
||||
p938x_dbg(chip, PR_IMPORTANT, "Running AICL to get back to max dc current\n");
|
||||
p938x_set_dc_aicl_rerun(chip);
|
||||
}
|
||||
|
||||
static int p938x_program_tx_fod(struct p938x_charger *chip,
|
||||
u8 *array, int array_len)
|
||||
{
|
||||
|
|
@ -1846,20 +1955,6 @@ static ssize_t boost_show(struct device *dev,
|
|||
p938x_get_boost(chip));
|
||||
}
|
||||
|
||||
static int p938x_set_dc_now_icl_ma(struct p938x_charger *chip, unsigned int idc)
|
||||
{
|
||||
union power_supply_propval val;
|
||||
|
||||
p938x_dbg(chip, PR_MOTO, "Setting IDC to %u mA\n", idc);
|
||||
|
||||
idc *= 1000; /* Convert to uA */
|
||||
val.intval = idc;
|
||||
|
||||
return p938x_set_dc_psp_prop(chip,
|
||||
POWER_SUPPLY_PROP_CURRENT_NOW,
|
||||
val);
|
||||
}
|
||||
|
||||
static ssize_t force_idc_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
|
|
@ -2800,6 +2895,7 @@ static int p938x_charger_probe(struct i2c_client *client,
|
|||
INIT_DELAYED_WORK(&chip->heartbeat_work, p938x_heartbeat_work);
|
||||
INIT_DELAYED_WORK(&chip->tx_mode_work, p938x_tx_mode_work);
|
||||
INIT_DELAYED_WORK(&chip->removal_work, p938x_removal_work);
|
||||
INIT_DELAYED_WORK(&chip->restore_idc_work, p938x_restore_idc_work);
|
||||
device_init_wakeup(chip->dev, true);
|
||||
|
||||
chip->regmap = regmap_init_i2c(client, &p938x_regmap_config);
|
||||
|
|
|
|||
Loading…
Reference in a new issue