power: smb1351-charger: update drive to support parallel architecture

Re-organize SMB1351 charger driver to support new parallel charger
architecture.
- New property "POWER_SUPPLY_PROP_PARALLEL_MODE" exposes the parallel
  charger configuration, in this case it is USBIN-USBIN configuration.
- Property "POWER_SUPPLY_CHARGE_TYPE" is added to report the current
  charge type and is also used for parallel charger chip detection.

Change-Id: I05692b34daef244f89a365e03043ae2ffe42d9da
Signed-off-by: Ashay Jaiswal <ashayj@codeaurora.org>
Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
This commit is contained in:
Ashay Jaiswal 2017-02-07 00:12:08 +05:30
parent 111ee8a2d1
commit 23d22ee4bf

View file

@ -461,7 +461,7 @@ struct smb1351_charger {
int parallel_pin_polarity_setting; int parallel_pin_polarity_setting;
bool parallel_charger; bool parallel_charger;
bool parallel_charger_present; bool parallel_charger_suspended;
bool bms_controlled_charging; bool bms_controlled_charging;
bool apsd_rerun; bool apsd_rerun;
bool usbin_ov; bool usbin_ov;
@ -1409,34 +1409,27 @@ static int smb1351_battery_get_property(struct power_supply *psy,
static enum power_supply_property smb1351_parallel_properties[] = { static enum power_supply_property smb1351_parallel_properties[] = {
POWER_SUPPLY_PROP_CHARGING_ENABLED, POWER_SUPPLY_PROP_CHARGING_ENABLED,
POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_PROP_STATUS,
POWER_SUPPLY_PROP_PRESENT,
POWER_SUPPLY_PROP_CURRENT_MAX, POWER_SUPPLY_PROP_CURRENT_MAX,
POWER_SUPPLY_PROP_VOLTAGE_MAX, POWER_SUPPLY_PROP_VOLTAGE_MAX,
POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED, POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED,
POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
POWER_SUPPLY_PROP_CHARGE_TYPE,
POWER_SUPPLY_PROP_PARALLEL_MODE, POWER_SUPPLY_PROP_PARALLEL_MODE,
}; };
static int smb1351_parallel_set_chg_present(struct smb1351_charger *chip, static int smb1351_parallel_set_chg_suspend(struct smb1351_charger *chip,
int present) int suspend)
{ {
int rc; int rc;
u8 reg, mask = 0; u8 reg, mask = 0;
if (present == chip->parallel_charger_present) { if (chip->parallel_charger_suspended == suspend) {
pr_debug("present %d -> %d, skipping\n", pr_debug("Skip same state request suspended = %d suspend=%d\n",
chip->parallel_charger_present, present); chip->parallel_charger_suspended, !suspend);
return 0; return 0;
} }
if (present) { if (!suspend) {
/* Check if SMB1351 is present */
rc = smb1351_read_reg(chip, CHG_REVISION_REG, &reg);
if (rc) {
pr_debug("Failed to detect smb1351-parallel-charger, may be absent\n");
return -ENODEV;
}
rc = smb_chip_get_version(chip); rc = smb_chip_get_version(chip);
if (rc) { if (rc) {
pr_err("Couldn't get version rc = %d\n", rc); pr_err("Couldn't get version rc = %d\n", rc);
@ -1476,6 +1469,26 @@ static int smb1351_parallel_set_chg_present(struct smb1351_charger *chip,
} }
} }
/* control USB suspend via command bits */
rc = smb1351_masked_write(chip, VARIOUS_FUNC_REG,
APSD_EN_BIT | SUSPEND_MODE_CTRL_BIT,
SUSPEND_MODE_CTRL_BY_I2C);
if (rc) {
pr_err("Couldn't set USB suspend rc=%d\n", rc);
return rc;
}
/*
* When present is being set force USB suspend, start charging
* only when POWER_SUPPLY_PROP_CURRENT_MAX is set.
*/
rc = smb1351_usb_suspend(chip, CURRENT, true);
if (rc) {
pr_err("failed to suspend rc=%d\n", rc);
return rc;
}
chip->usb_psy_ma = SUSPEND_CURRENT_MA;
/* set chg en by pin active low */ /* set chg en by pin active low */
reg = chip->parallel_pin_polarity_setting | USBCS_CTRL_BY_I2C; reg = chip->parallel_pin_polarity_setting | USBCS_CTRL_BY_I2C;
rc = smb1351_masked_write(chip, CHG_PIN_EN_CTRL_REG, rc = smb1351_masked_write(chip, CHG_PIN_EN_CTRL_REG,
@ -1485,15 +1498,6 @@ static int smb1351_parallel_set_chg_present(struct smb1351_charger *chip,
return rc; return rc;
} }
/* control USB suspend via command bits */
rc = smb1351_masked_write(chip, VARIOUS_FUNC_REG,
SUSPEND_MODE_CTRL_BIT,
SUSPEND_MODE_CTRL_BY_I2C);
if (rc) {
pr_err("Couldn't set USB suspend rc=%d\n", rc);
return rc;
}
/* /*
* setup USB 2.0/3.0 detection and USB 500/100 * setup USB 2.0/3.0 detection and USB 500/100
* command polarity * command polarity
@ -1508,23 +1512,21 @@ static int smb1351_parallel_set_chg_present(struct smb1351_charger *chip,
return rc; return rc;
} }
/* set fast charging current limit */
chip->target_fastchg_current_max_ma = SMB1351_CHG_FAST_MIN_MA;
rc = smb1351_fastchg_current_set(chip, rc = smb1351_fastchg_current_set(chip,
chip->target_fastchg_current_max_ma); chip->target_fastchg_current_max_ma);
if (rc) { if (rc) {
pr_err("Couldn't set fastchg current rc=%d\n", rc); pr_err("Couldn't set fastchg current rc=%d\n", rc);
return rc; return rc;
} }
} chip->parallel_charger_suspended = false;
} else {
rc = smb1351_usb_suspend(chip, CURRENT, true);
if (rc)
pr_debug("failed to suspend rc=%d\n", rc);
chip->parallel_charger_present = present; chip->usb_psy_ma = SUSPEND_CURRENT_MA;
/* chip->parallel_charger_suspended = true;
* When present is being set force USB suspend, start charging }
* only when POWER_SUPPLY_PROP_CURRENT_MAX is set.
*/
chip->usb_psy_ma = SUSPEND_CURRENT_MA;
smb1351_usb_suspend(chip, CURRENT, true);
return 0; return 0;
} }
@ -1564,6 +1566,31 @@ static bool smb1351_is_input_current_limited(struct smb1351_charger *chip)
return !!(reg & IRQ_IC_LIMIT_STATUS_BIT); return !!(reg & IRQ_IC_LIMIT_STATUS_BIT);
} }
static bool smb1351_is_usb_present(struct smb1351_charger *chip)
{
int rc;
union power_supply_propval val = {0, };
if (!chip->usb_psy)
chip->usb_psy = power_supply_get_by_name("usb");
if (!chip->usb_psy) {
pr_err("USB psy not found\n");
return false;
}
rc = power_supply_get_property(chip->usb_psy,
POWER_SUPPLY_PROP_ONLINE, &val);
if (rc < 0) {
pr_err("Failed to get present property rc=%d\n", rc);
return false;
}
if (val.intval)
return true;
return false;
}
static int smb1351_parallel_set_property(struct power_supply *psy, static int smb1351_parallel_set_property(struct power_supply *psy,
enum power_supply_property prop, enum power_supply_property prop,
const union power_supply_propval *val) const union power_supply_propval *val)
@ -1577,38 +1604,30 @@ static int smb1351_parallel_set_property(struct power_supply *psy,
*CHG EN is controlled by pin in the parallel charging. *CHG EN is controlled by pin in the parallel charging.
*Use suspend if disable charging by command. *Use suspend if disable charging by command.
*/ */
if (chip->parallel_charger_present) if (!chip->parallel_charger_suspended)
rc = smb1351_usb_suspend(chip, USER, !val->intval); rc = smb1351_usb_suspend(chip, USER, !val->intval);
break; break;
case POWER_SUPPLY_PROP_PRESENT: case POWER_SUPPLY_PROP_INPUT_SUSPEND:
rc = smb1351_parallel_set_chg_present(chip, val->intval); rc = smb1351_parallel_set_chg_suspend(chip, val->intval);
break; break;
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
if (chip->parallel_charger_present) { chip->target_fastchg_current_max_ma =
chip->target_fastchg_current_max_ma =
val->intval / 1000; val->intval / 1000;
if (!chip->parallel_charger_suspended)
rc = smb1351_fastchg_current_set(chip, rc = smb1351_fastchg_current_set(chip,
chip->target_fastchg_current_max_ma); chip->target_fastchg_current_max_ma);
}
break; break;
case POWER_SUPPLY_PROP_CURRENT_MAX: case POWER_SUPPLY_PROP_CURRENT_MAX:
if (chip->parallel_charger_present) { index = smb1351_get_closest_usb_setpoint(val->intval / 1000);
index = smb1351_get_closest_usb_setpoint( chip->usb_psy_ma = usb_chg_current[index];
val->intval / 1000); if (!chip->parallel_charger_suspended)
chip->usb_psy_ma = usb_chg_current[index];
rc = smb1351_set_usb_chg_current(chip, rc = smb1351_set_usb_chg_current(chip,
chip->usb_psy_ma); chip->usb_psy_ma);
}
break; break;
case POWER_SUPPLY_PROP_VOLTAGE_MAX: case POWER_SUPPLY_PROP_VOLTAGE_MAX:
if (chip->parallel_charger_present && chip->vfloat_mv = val->intval / 1000;
(chip->vfloat_mv != val->intval)) { if (!chip->parallel_charger_suspended)
rc = smb1351_float_voltage_set(chip, val->intval); rc = smb1351_float_voltage_set(chip, val->intval);
if (!rc)
chip->vfloat_mv = val->intval;
} else {
chip->vfloat_mv = val->intval;
}
break; break;
default: default:
return -EINVAL; return -EINVAL;
@ -1638,41 +1657,49 @@ static int smb1351_parallel_get_property(struct power_supply *psy,
val->intval = !chip->usb_suspended_status; val->intval = !chip->usb_suspended_status;
break; break;
case POWER_SUPPLY_PROP_CURRENT_MAX: case POWER_SUPPLY_PROP_CURRENT_MAX:
if (chip->parallel_charger_present) if (!chip->parallel_charger_suspended)
val->intval = chip->usb_psy_ma * 1000; val->intval = chip->usb_psy_ma * 1000;
else else
val->intval = 0; val->intval = 0;
break; break;
case POWER_SUPPLY_PROP_VOLTAGE_MAX: case POWER_SUPPLY_PROP_VOLTAGE_MAX:
val->intval = chip->vfloat_mv; if (!chip->parallel_charger_suspended)
val->intval = chip->vfloat_mv;
else
val->intval = 0;
break; break;
case POWER_SUPPLY_PROP_PRESENT: case POWER_SUPPLY_PROP_CHARGE_TYPE:
val->intval = chip->parallel_charger_present; val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE;
/* Check if SMB1351 is present */
if (smb1351_is_usb_present(chip)) {
val->intval = smb1351_get_prop_charge_type(chip);
if (val->intval == POWER_SUPPLY_CHARGE_TYPE_UNKNOWN) {
pr_debug("Failed to charge type, charger may be absent\n");
return -ENODEV;
}
}
break; break;
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
if (chip->parallel_charger_present) if (!chip->parallel_charger_suspended)
val->intval = chip->fastchg_current_max_ma * 1000; val->intval = chip->fastchg_current_max_ma * 1000;
else else
val->intval = 0; val->intval = 0;
break; break;
case POWER_SUPPLY_PROP_STATUS: case POWER_SUPPLY_PROP_STATUS:
if (chip->parallel_charger_present) if (!chip->parallel_charger_suspended)
val->intval = smb1351_get_prop_batt_status(chip); val->intval = smb1351_get_prop_batt_status(chip);
else else
val->intval = POWER_SUPPLY_STATUS_DISCHARGING; val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
break; break;
case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED: case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED:
if (chip->parallel_charger_present) if (!chip->parallel_charger_suspended)
val->intval = val->intval =
smb1351_is_input_current_limited(chip) ? 1 : 0; smb1351_is_input_current_limited(chip) ? 1 : 0;
else else
val->intval = 0; val->intval = 0;
break; break;
case POWER_SUPPLY_PROP_PARALLEL_MODE: case POWER_SUPPLY_PROP_PARALLEL_MODE:
if (chip->parallel_charger_present) val->intval = POWER_SUPPLY_PARALLEL_USBIN_USBIN;
val->intval = POWER_SUPPLY_PARALLEL_USBIN_USBIN;
else
val->intval = POWER_SUPPLY_PARALLEL_NONE;
break; break;
default: default:
return -EINVAL; return -EINVAL;
@ -3142,6 +3169,7 @@ static int smb1351_parallel_charger_probe(struct i2c_client *client,
chip->client = client; chip->client = client;
chip->dev = &client->dev; chip->dev = &client->dev;
chip->parallel_charger = true; chip->parallel_charger = true;
chip->parallel_charger_suspended = true;
chip->usb_suspended_status = of_property_read_bool(node, chip->usb_suspended_status = of_property_read_bool(node,
"qcom,charging-disabled"); "qcom,charging-disabled");