Merge "qcom: smb2: Disable parallel charging on qnovo charging below 2A"
This commit is contained in:
commit
56aaf096d9
3 changed files with 100 additions and 46 deletions
|
@ -29,6 +29,7 @@
|
|||
#define QNOVO_PTRAIN_STS 0x08
|
||||
#define QNOVO_ERROR_STS 0x09
|
||||
#define QNOVO_ERROR_BIT BIT(0)
|
||||
#define QNOVO_ERROR_STS2 0x0A
|
||||
#define QNOVO_INT_RT_STS 0x10
|
||||
#define QNOVO_INT_SET_TYPE 0x11
|
||||
#define QNOVO_INT_POLARITY_HIGH 0x12
|
||||
|
@ -272,28 +273,22 @@ static int qnovo_disable_cb(struct votable *votable, void *data, int disable,
|
|||
const char *client)
|
||||
{
|
||||
struct qnovo *chip = data;
|
||||
int rc = 0;
|
||||
union power_supply_propval pval = {0};
|
||||
int rc;
|
||||
|
||||
if (disable) {
|
||||
rc = qnovo_batt_psy_update(chip, true);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
}
|
||||
if (!is_batt_available(chip))
|
||||
return -EINVAL;
|
||||
|
||||
rc = qnovo_masked_write(chip, QNOVO_PTRAIN_EN, QNOVO_PTRAIN_EN_BIT,
|
||||
disable ? 0 : QNOVO_PTRAIN_EN_BIT);
|
||||
pval.intval = !disable;
|
||||
rc = power_supply_set_property(chip->batt_psy,
|
||||
POWER_SUPPLY_PROP_CHARGE_QNOVO_ENABLE,
|
||||
&pval);
|
||||
if (rc < 0) {
|
||||
dev_err(chip->dev, "Couldn't %s pulse train rc=%d\n",
|
||||
disable ? "disable" : "enable", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (!disable) {
|
||||
rc = qnovo_batt_psy_update(chip, false);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
pr_err("Couldn't set prop qnovo_enable rc = %d\n", rc);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = qnovo_batt_psy_update(chip, disable);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -348,13 +343,15 @@ static int qnovo_check_chg_version(struct qnovo *chip)
|
|||
enum {
|
||||
VER = 0,
|
||||
OK_TO_QNOVO,
|
||||
ENABLE,
|
||||
QNOVO_ENABLE,
|
||||
PT_ENABLE,
|
||||
FV_REQUEST,
|
||||
FCC_REQUEST,
|
||||
PE_CTRL_REG,
|
||||
PE_CTRL2_REG,
|
||||
PTRAIN_STS_REG,
|
||||
INT_RT_STS_REG,
|
||||
ERR_STS2_REG,
|
||||
PREST1,
|
||||
PPULS1,
|
||||
NREST1,
|
||||
|
@ -394,6 +391,12 @@ struct param_info {
|
|||
};
|
||||
|
||||
static struct param_info params[] = {
|
||||
[PT_ENABLE] = {
|
||||
.name = "PT_ENABLE",
|
||||
.start_addr = QNOVO_PTRAIN_EN,
|
||||
.num_regs = 1,
|
||||
.units_str = "",
|
||||
},
|
||||
[FV_REQUEST] = {
|
||||
.units_str = "uV",
|
||||
},
|
||||
|
@ -424,6 +427,12 @@ static struct param_info params[] = {
|
|||
.num_regs = 1,
|
||||
.units_str = "",
|
||||
},
|
||||
[ERR_STS2_REG] = {
|
||||
.name = "RAW_CHGR_ERR",
|
||||
.start_addr = QNOVO_ERROR_STS2,
|
||||
.num_regs = 1,
|
||||
.units_str = "",
|
||||
},
|
||||
[PREST1] = {
|
||||
.name = "PREST1",
|
||||
.start_addr = QNOVO_PREST1_CTRL,
|
||||
|
@ -648,30 +657,70 @@ static ssize_t ok_to_qnovo_show(struct class *c, struct class_attribute *attr,
|
|||
return snprintf(buf, PAGE_SIZE, "%d\n", chip->cs.ok_to_qnovo);
|
||||
}
|
||||
|
||||
static ssize_t enable_show(struct class *c, struct class_attribute *attr,
|
||||
static ssize_t qnovo_enable_show(struct class *c, struct class_attribute *attr,
|
||||
char *ubuf)
|
||||
{
|
||||
struct qnovo *chip = container_of(c, struct qnovo, qnovo_class);
|
||||
int val;
|
||||
int val = get_effective_result(chip->disable_votable);
|
||||
|
||||
val = get_client_vote(chip->disable_votable, USER_VOTER);
|
||||
val = !val;
|
||||
return snprintf(ubuf, PAGE_SIZE, "%d\n", val);
|
||||
return snprintf(ubuf, PAGE_SIZE, "%d\n", !val);
|
||||
}
|
||||
|
||||
static ssize_t enable_store(struct class *c, struct class_attribute *attr,
|
||||
static ssize_t qnovo_enable_store(struct class *c, struct class_attribute *attr,
|
||||
const char *ubuf, size_t count)
|
||||
{
|
||||
struct qnovo *chip = container_of(c, struct qnovo, qnovo_class);
|
||||
unsigned long val;
|
||||
bool disable;
|
||||
|
||||
if (kstrtoul(ubuf, 0, &val))
|
||||
return -EINVAL;
|
||||
|
||||
disable = !val;
|
||||
vote(chip->disable_votable, USER_VOTER, !val, 0);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t pt_enable_show(struct class *c, struct class_attribute *attr,
|
||||
char *ubuf)
|
||||
{
|
||||
int i = attr - qnovo_attributes;
|
||||
struct qnovo *chip = container_of(c, struct qnovo, qnovo_class);
|
||||
u8 buf[2] = {0, 0};
|
||||
u16 regval;
|
||||
int rc;
|
||||
|
||||
rc = qnovo_read(chip, params[i].start_addr, buf, params[i].num_regs);
|
||||
if (rc < 0) {
|
||||
pr_err("Couldn't read %s rc = %d\n", params[i].name, rc);
|
||||
return -EINVAL;
|
||||
}
|
||||
regval = buf[1] << 8 | buf[0];
|
||||
|
||||
return snprintf(ubuf, PAGE_SIZE, "%d\n",
|
||||
(int)(regval & QNOVO_PTRAIN_EN_BIT));
|
||||
}
|
||||
|
||||
static ssize_t pt_enable_store(struct class *c, struct class_attribute *attr,
|
||||
const char *ubuf, size_t count)
|
||||
{
|
||||
struct qnovo *chip = container_of(c, struct qnovo, qnovo_class);
|
||||
unsigned long val;
|
||||
int rc = 0;
|
||||
|
||||
if (get_effective_result(chip->disable_votable))
|
||||
return -EINVAL;
|
||||
|
||||
if (kstrtoul(ubuf, 0, &val))
|
||||
return -EINVAL;
|
||||
|
||||
rc = qnovo_masked_write(chip, QNOVO_PTRAIN_EN, QNOVO_PTRAIN_EN_BIT,
|
||||
(bool)val ? QNOVO_PTRAIN_EN_BIT : 0);
|
||||
if (rc < 0) {
|
||||
dev_err(chip->dev, "Couldn't %s pulse train rc=%d\n",
|
||||
(bool)val ? "enable" : "disable", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
vote(chip->disable_votable, USER_VOTER, disable, 0);
|
||||
return count;
|
||||
}
|
||||
|
||||
|
@ -698,6 +747,9 @@ static ssize_t val_store(struct class *c, struct class_attribute *attr,
|
|||
int i = attr - qnovo_attributes;
|
||||
unsigned long val;
|
||||
|
||||
if (get_effective_result(chip->disable_votable))
|
||||
return -EINVAL;
|
||||
|
||||
if (kstrtoul(ubuf, 0, &val))
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -707,6 +759,8 @@ static ssize_t val_store(struct class *c, struct class_attribute *attr,
|
|||
if (i == FCC_REQUEST)
|
||||
chip->fcc_uA_request = val;
|
||||
|
||||
qnovo_batt_psy_update(chip, false);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
@ -1016,8 +1070,8 @@ static ssize_t batt_prop_show(struct class *c, struct class_attribute *attr,
|
|||
static struct class_attribute qnovo_attributes[] = {
|
||||
[VER] = __ATTR_RO(version),
|
||||
[OK_TO_QNOVO] = __ATTR_RO(ok_to_qnovo),
|
||||
[ENABLE] = __ATTR(enable, 0644,
|
||||
enable_show, enable_store),
|
||||
[QNOVO_ENABLE] = __ATTR_RW(qnovo_enable),
|
||||
[PT_ENABLE] = __ATTR_RW(pt_enable),
|
||||
[FV_REQUEST] = __ATTR(fv_uV_request, 0644,
|
||||
val_show, val_store),
|
||||
[FCC_REQUEST] = __ATTR(fcc_uA_request, 0644,
|
||||
|
@ -1030,6 +1084,8 @@ static struct class_attribute qnovo_attributes[] = {
|
|||
reg_show, NULL),
|
||||
[INT_RT_STS_REG] = __ATTR(INT_RT_STS_REG, 0444,
|
||||
reg_show, NULL),
|
||||
[ERR_STS2_REG] = __ATTR(ERR_STS2_REG, 0444,
|
||||
reg_show, NULL),
|
||||
[PREST1] = __ATTR(PREST1_mS, 0644,
|
||||
time_show, time_store),
|
||||
[PPULS1] = __ATTR(PPULS1_uC, 0644,
|
||||
|
@ -1050,7 +1106,7 @@ static struct class_attribute qnovo_attributes[] = {
|
|||
time_show, NULL),
|
||||
[PREST2] = __ATTR(PREST2_mS, 0644,
|
||||
time_show, time_store),
|
||||
[PPULS2] = __ATTR(PPULS2_mS, 0644,
|
||||
[PPULS2] = __ATTR(PPULS2_uC, 0644,
|
||||
coulomb_show, coulomb_store),
|
||||
[NREST2] = __ATTR(NREST2_mS, 0644,
|
||||
time_show, time_store),
|
||||
|
@ -1135,8 +1191,7 @@ static void get_chg_status(struct qnovo *chip, const struct chg_props *cp,
|
|||
{
|
||||
cs->ok_to_qnovo = false;
|
||||
|
||||
if (cp->charging &&
|
||||
(cp->usb_online || cp->dc_online))
|
||||
if (cp->charging && (cp->usb_online || cp->dc_online))
|
||||
cs->ok_to_qnovo = true;
|
||||
}
|
||||
|
||||
|
@ -1152,17 +1207,10 @@ static void status_change_work(struct work_struct *work)
|
|||
get_chg_status(chip, &cp, &cs);
|
||||
|
||||
if (cs.ok_to_qnovo ^ chip->cs.ok_to_qnovo) {
|
||||
/*
|
||||
* when it is not okay to Qnovo charge, disable both voters,
|
||||
* so that when it becomes okay to Qnovo charge the user voter
|
||||
* has to specifically enable its vote to being Qnovo charging
|
||||
*/
|
||||
if (!cs.ok_to_qnovo) {
|
||||
vote(chip->disable_votable, OK_TO_QNOVO_VOTER, 1, 0);
|
||||
vote(chip->disable_votable, USER_VOTER, 1, 0);
|
||||
} else {
|
||||
vote(chip->disable_votable, OK_TO_QNOVO_VOTER, 0, 0);
|
||||
}
|
||||
vote(chip->disable_votable, OK_TO_QNOVO_VOTER,
|
||||
!cs.ok_to_qnovo, 0);
|
||||
if (!cs.ok_to_qnovo)
|
||||
vote(chip->disable_votable, USER_VOTER, true, 0);
|
||||
notify_uevent = true;
|
||||
}
|
||||
|
||||
|
@ -1192,8 +1240,6 @@ static irqreturn_t handle_ptrain_done(int irq, void *data)
|
|||
{
|
||||
struct qnovo *chip = data;
|
||||
|
||||
/* disable user voter here */
|
||||
vote(chip->disable_votable, USER_VOTER, 0, 0);
|
||||
kobject_uevent(&chip->dev->kobj, KOBJ_CHANGE);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
@ -1206,7 +1252,7 @@ static int qnovo_hw_init(struct qnovo *chip)
|
|||
u8 vadc_offset, vadc_gain;
|
||||
u8 val;
|
||||
|
||||
vote(chip->disable_votable, USER_VOTER, 1, 0);
|
||||
vote(chip->disable_votable, USER_VOTER, true, 0);
|
||||
|
||||
val = 0;
|
||||
rc = qnovo_write(chip, QNOVO_STRM_CTRL, &val, 1);
|
||||
|
@ -1318,6 +1364,9 @@ static int qnovo_request_interrupts(struct qnovo *chip)
|
|||
irq_ptrain_done, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
enable_irq_wake(irq_ptrain_done);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -1399,6 +1448,8 @@ static int qnovo_probe(struct platform_device *pdev)
|
|||
goto unreg_notifier;
|
||||
}
|
||||
|
||||
device_init_wakeup(chip->dev, true);
|
||||
|
||||
return rc;
|
||||
|
||||
unreg_notifier:
|
||||
|
|
|
@ -999,6 +999,8 @@ static int smb2_batt_set_prop(struct power_supply *psy,
|
|||
break;
|
||||
case POWER_SUPPLY_PROP_CURRENT_QNOVO:
|
||||
chg->qnovo_fcc_ua = val->intval;
|
||||
vote(chg->pl_disable_votable, PL_QNOVO_VOTER,
|
||||
val->intval != -EINVAL && val->intval < 2000000, 0);
|
||||
rc = rerun_election(chg->fcc_votable);
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
|
||||
|
|
|
@ -37,6 +37,7 @@ enum print_reason {
|
|||
#define USB_PSY_VOTER "USB_PSY_VOTER"
|
||||
#define PL_TAPER_WORK_RUNNING_VOTER "PL_TAPER_WORK_RUNNING_VOTER"
|
||||
#define PL_INDIRECT_VOTER "PL_INDIRECT_VOTER"
|
||||
#define PL_QNOVO_VOTER "PL_QNOVO_VOTER"
|
||||
#define USBIN_I_VOTER "USBIN_I_VOTER"
|
||||
#define USBIN_V_VOTER "USBIN_V_VOTER"
|
||||
#define CHG_STATE_VOTER "CHG_STATE_VOTER"
|
||||
|
|
Loading…
Add table
Reference in a new issue