summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorHarry Yang <harryy@codeaurora.org>2017-02-24 01:06:00 -0800
committerHarry Yang <harryy@codeaurora.org>2017-03-28 22:56:59 -0700
commit8ae4a028b645ae567860bdbb6e669a93e9362b99 (patch)
treefd606bfc90eac6855872de1a3cd3ae505062b272 /drivers
parentfec225ae45829184255a95a00d81cf1387fd6a84 (diff)
qcom: qnovo: Add support to enable qnovo charging
Add property qnovo_enable to enable qnovo charging. Also add property pt_enable to enable pulse train. Extend QNOVO algorithm's control of voltage and current after pulse train stops and as long as qnovo_enable = 1. The interrupt ptrain_done is configured wakeup capable. CRs-Fixed: 2013069 Change-Id: Icb61e0e0169283f5f52a4994431489dde0af1c73 Signed-off-by: Harry Yang <harryy@codeaurora.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/power/supply/qcom/qpnp-qnovo.c133
1 files changed, 87 insertions, 46 deletions
diff --git a/drivers/power/supply/qcom/qpnp-qnovo.c b/drivers/power/supply/qcom/qpnp-qnovo.c
index ada231905df9..2050785b0755 100644
--- a/drivers/power/supply/qcom/qpnp-qnovo.c
+++ b/drivers/power/supply/qcom/qpnp-qnovo.c
@@ -272,28 +272,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,7 +342,8 @@ 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,
@@ -394,6 +389,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",
},
@@ -648,30 +649,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 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;
+
+ if (kstrtoul(ubuf, 0, &val))
+ return -EINVAL;
+
+ 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 enable_store(struct class *c, struct class_attribute *attr,
+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;
- bool disable;
+ int rc = 0;
+
+ if (get_effective_result(chip->disable_votable))
+ return -EINVAL;
if (kstrtoul(ubuf, 0, &val))
return -EINVAL;
- disable = !val;
+ 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 +739,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 +751,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 +1062,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,
@@ -1050,7 +1096,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 +1181,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 +1197,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 +1230,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 +1242,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 +1354,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 +1438,8 @@ static int qnovo_probe(struct platform_device *pdev)
goto unreg_notifier;
}
+ device_init_wakeup(chip->dev, true);
+
return rc;
unreg_notifier: