diff --git a/drivers/power/supply/bq25890_charger.c b/drivers/power/supply/bq25890_charger.c index c33885e4f48c0703015038315ca72112cf6318c4..0c7f05fa4145111cebf5b49f41c786e4ef4e43a5 100644 --- a/drivers/power/supply/bq25890_charger.c +++ b/drivers/power/supply/bq25890_charger.c @@ -98,6 +98,7 @@ struct bq25890_state { u8 vsys_status; u8 boost_fault; u8 bat_fault; + u8 ntc_fault; }; struct bq25890_device { @@ -277,6 +278,7 @@ enum bq25890_table_ids { /* lookup tables */ TBL_TREG, TBL_BOOSTI, + TBL_TSPCT, }; /* Thermal Regulation Threshold lookup table, in degrees Celsius */ @@ -291,6 +293,28 @@ static const u32 bq25890_boosti_tbl[] = { #define BQ25890_BOOSTI_TBL_SIZE ARRAY_SIZE(bq25890_boosti_tbl) +/* NTC 10K temperature lookup table in thenths of a degree */ +static const u32 bq25890_tspct_tbl[] = { + 850, 840, 830, 820, 810, 800, 790, 780, + 770, 760, 750, 740, 730, 720, 710, 700, + 690, 685, 680, 675, 670, 660, 650, 645, + 640, 630, 620, 615, 610, 600, 590, 585, + 580, 570, 565, 560, 550, 540, 535, 530, + 520, 515, 510, 500, 495, 490, 480, 475, + 470, 460, 455, 450, 440, 435, 430, 425, + 420, 410, 405, 400, 390, 385, 380, 370, + 365, 360, 355, 350, 340, 335, 330, 320, + 310, 305, 300, 290, 285, 280, 275, 270, + 260, 250, 245, 240, 230, 225, 220, 210, + 205, 200, 190, 180, 175, 170, 160, 150, + 145, 140, 130, 120, 115, 110, 100, 90, + 80, 70, 60, 50, 40, 30, 20, 10, + 0, -10, -20, -30, -40, -60, -70, -80, + -90, -10, -120, -140, -150, -170, -190, -210, +}; + +#define BQ25890_TSPCT_TBL_SIZE ARRAY_SIZE(bq25890_tspct_tbl) + struct bq25890_range { u32 min; u32 max; @@ -321,7 +345,8 @@ static const union { /* lookup tables */ [TBL_TREG] = { .lt = {bq25890_treg_tbl, BQ25890_TREG_TBL_SIZE} }, - [TBL_BOOSTI] = { .lt = {bq25890_boosti_tbl, BQ25890_BOOSTI_TBL_SIZE} } + [TBL_BOOSTI] = { .lt = {bq25890_boosti_tbl, BQ25890_BOOSTI_TBL_SIZE} }, + [TBL_TSPCT] = { .lt = {bq25890_tspct_tbl, BQ25890_TSPCT_TBL_SIZE} } }; static int bq25890_field_read(struct bq25890_device *bq, @@ -396,6 +421,14 @@ enum bq25890_chrg_fault { CHRG_FAULT_TIMER_EXPIRED, }; +enum bq25890_ntc_fault { + NTC_FAULT_NORMAL, + NTC_FAULT_BUCK_COLD, + NTC_FAULT_BUCK_HOT, + NTC_FAULT_BOOST_COLD = 5, + NTC_FAULT_BOOST_HOT +}; + static bool bq25890_is_adc_property(enum power_supply_property psp) { switch (psp) { @@ -473,14 +506,19 @@ static int bq25890_power_supply_get_property(struct power_supply *psy, break; case POWER_SUPPLY_PROP_HEALTH: - if (!state.chrg_fault && !state.bat_fault && !state.boost_fault) + if (!state.chrg_fault && !state.bat_fault && !state.boost_fault && !state.ntc_fault) val->intval = POWER_SUPPLY_HEALTH_GOOD; else if (state.bat_fault) val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE; else if (state.chrg_fault == CHRG_FAULT_TIMER_EXPIRED) val->intval = POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE; - else if (state.chrg_fault == CHRG_FAULT_THERMAL_SHUTDOWN) + else if (state.chrg_fault == CHRG_FAULT_THERMAL_SHUTDOWN || + state.ntc_fault == NTC_FAULT_BUCK_HOT || + state.ntc_fault == NTC_FAULT_BOOST_HOT) val->intval = POWER_SUPPLY_HEALTH_OVERHEAT; + else if (state.ntc_fault == NTC_FAULT_BUCK_COLD || + state.ntc_fault == NTC_FAULT_BOOST_COLD) + val->intval = POWER_SUPPLY_HEALTH_COLD; else val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE; break; @@ -556,6 +594,16 @@ static int bq25890_power_supply_get_property(struct power_supply *psy, dev_info(bq->dev, "Capacity for %d is %d%%", ocv, val->intval); break; + case POWER_SUPPLY_PROP_TEMP: + ret = bq25890_field_read(bq, F_TSPCT); + if (ret < 0) + return ret; + + /* convert TS percentage into rough temperature */ + val->intval = bq25890_find_val(ret, TBL_TSPCT); + break; + + default: return -EINVAL; } @@ -577,7 +625,8 @@ static int bq25890_get_chip_state(struct bq25890_device *bq, {F_VSYS_STAT, &state->vsys_status}, {F_BOOST_FAULT, &state->boost_fault}, {F_BAT_FAULT, &state->bat_fault}, - {F_CHG_FAULT, &state->chrg_fault} + {F_CHG_FAULT, &state->chrg_fault}, + {F_NTC_FAULT, &state->ntc_fault} }; for (i = 0; i < ARRAY_SIZE(state_fields); i++) { @@ -588,13 +637,41 @@ static int bq25890_get_chip_state(struct bq25890_device *bq, *state_fields[i].data = ret; } - dev_dbg(bq->dev, "S:CHG/PG/VSYS=%d/%d/%d, F:CHG/BOOST/BAT=%d/%d/%d\n", + dev_dbg(bq->dev, "S:CHG/PG/VSYS=%d/%d/%d, F:CHG/BOOST/BAT/NTC=%d/%d/%d/%d\n", state->chrg_status, state->online, state->vsys_status, - state->chrg_fault, state->boost_fault, state->bat_fault); + state->chrg_fault, state->boost_fault, state->bat_fault, + state->ntc_fault); return 0; } +static void bq25890_log_ntc_faults(struct bq25890_device *bq, struct bq25890_state *new_state) +{ + if (new_state->ntc_fault != bq->state.ntc_fault) + return; + + switch(new_state->ntc_fault) { + case NTC_FAULT_NORMAL: + dev_info(bq->dev, "NTC state normal\n"); + break; + case NTC_FAULT_BOOST_COLD: + dev_err(bq->dev, "NTC state boost cold\n"); + break; + case NTC_FAULT_BOOST_HOT: + dev_err(bq->dev, "NTC state boost hot\n"); + break; + case NTC_FAULT_BUCK_COLD: + dev_err(bq->dev, "NTC state buck cold\n"); + break; + case NTC_FAULT_BUCK_HOT: + dev_err(bq->dev, "NTC state buck hot\n"); + break; + default: + dev_err(bq->dev, "NTC state UNKNOWN\n"); + break; + } +} + static irqreturn_t __bq25890_handle_irq(struct bq25890_device *bq) { struct bq25890_state new_state; @@ -607,6 +684,17 @@ static irqreturn_t __bq25890_handle_irq(struct bq25890_device *bq) if (!memcmp(&bq->state, &new_state, sizeof(new_state))) return IRQ_NONE; + bq25890_log_ntc_faults(bq, &new_state); + + if (new_state.chrg_fault != bq->state.chrg_fault) { + if(new_state.chrg_fault) + dev_err(bq->dev, "Charge fault - new fault old: %d new: %d\n", + bq->state.chrg_fault, new_state.chrg_fault); + else + dev_info(bq->dev, "Charge fault - fault cleared old: %d new: %d\n", + bq->state.chrg_fault, new_state.chrg_fault); + } + if (!new_state.online && bq->state.online) { /* power removed */ /* disable ADC */ ret = bq25890_field_write(bq, F_CONV_RATE, 0); @@ -753,6 +841,7 @@ static const enum power_supply_property bq25890_power_supply_props[] = { POWER_SUPPLY_PROP_VOLTAGE_NOW, POWER_SUPPLY_PROP_CURRENT_NOW, POWER_SUPPLY_PROP_CAPACITY, + POWER_SUPPLY_PROP_TEMP, }; static char *bq25890_charger_supplied_to[] = {