regulator: qpnp-labibb: do not disable IBB when entering TTW mode
Currently when entering touch-to-wakeup (TTW) mode, IBB module is disabled as part of the regulator_disable sequence before applying the settings needed for SWIRE control in TTW mode. This causes adversary effects such as droop in the VDISN voltage rail. To avoid this, as per the hardware documentation, do not disable IBB module through IBB_ENABLE_CTL when LABIBB regulators are disabled and entering TTW mode. Instead, just enter TTW mode and mark the regulators disabled. Normal mode settings will be applied when the regulators are enabled again as before. While at it, add a centralized function qpnp_ibb_mode() to write to IBB_ENABLE_CTL register. CRs-Fixed: 952847 Change-Id: I74c6ba411091d146ab5719c2d72d6385fa90af21 Signed-off-by: Subbaraman Narayanamurthy <subbaram@codeaurora.org>
This commit is contained in:
parent
44626b79a8
commit
8ac740251d
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
|
@ -159,6 +159,7 @@
|
|||
#define IBB_MODULE_RDY_EN BIT(7)
|
||||
|
||||
/* REG_IBB_ENABLE_CTL */
|
||||
#define IBB_ENABLE_CTL_MASK (BIT(7) | BIT(6))
|
||||
#define IBB_ENABLE_CTL_SWIRE_RDY BIT(6)
|
||||
#define IBB_ENABLE_CTL_MODULE_EN BIT(7)
|
||||
|
||||
|
@ -232,6 +233,17 @@ enum qpnp_labibb_mode {
|
|||
QPNP_LABIBB_MAX_MODE,
|
||||
};
|
||||
|
||||
/**
|
||||
* IBB_SW_CONTROL_EN: Specifies IBB is enabled through software.
|
||||
* IBB_SW_CONTROL_DIS: Specifies IBB is disabled through software.
|
||||
* IBB_HW_CONTROL: Specifies IBB is controlled through SWIRE (hardware).
|
||||
*/
|
||||
enum ibb_mode {
|
||||
IBB_SW_CONTROL_EN,
|
||||
IBB_SW_CONTROL_DIS,
|
||||
IBB_HW_CONTROL,
|
||||
};
|
||||
|
||||
static const int ibb_discharge_resistor_plan[] = {
|
||||
300,
|
||||
64,
|
||||
|
@ -595,6 +607,29 @@ static int qpnp_labibb_get_matching_idx(const char *val)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int qpnp_ibb_set_mode(struct qpnp_labibb *labibb, enum ibb_mode mode)
|
||||
{
|
||||
int rc;
|
||||
u8 val;
|
||||
|
||||
if (mode == IBB_SW_CONTROL_EN)
|
||||
val = IBB_ENABLE_CTL_MODULE_EN;
|
||||
else if (mode == IBB_HW_CONTROL)
|
||||
val = IBB_ENABLE_CTL_SWIRE_RDY;
|
||||
else if (mode == IBB_SW_CONTROL_DIS)
|
||||
val = 0;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
rc = qpnp_labibb_masked_write(labibb,
|
||||
labibb->ibb_base + REG_IBB_ENABLE_CTL,
|
||||
IBB_ENABLE_CTL_MASK, val, 1);
|
||||
if (rc)
|
||||
pr_err("Unable to configure IBB_ENABLE_CTL rc=%d\n", rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int qpnp_lab_dt_init(struct qpnp_labibb *labibb,
|
||||
struct device_node *of_node)
|
||||
{
|
||||
|
@ -837,9 +872,7 @@ static int qpnp_lab_dt_init(struct qpnp_labibb *labibb,
|
|||
}
|
||||
|
||||
if (labibb->swire_control) {
|
||||
val = IBB_ENABLE_CTL_SWIRE_RDY;
|
||||
rc = qpnp_labibb_write(labibb,
|
||||
labibb->ibb_base + REG_IBB_ENABLE_CTL, &val, 1);
|
||||
rc = qpnp_ibb_set_mode(labibb, IBB_HW_CONTROL);
|
||||
if (rc)
|
||||
pr_err("Unable to set SWIRE_RDY rc=%d\n", rc);
|
||||
}
|
||||
|
@ -1016,12 +1049,9 @@ static int qpnp_labibb_regulator_ttw_mode_enter(struct qpnp_labibb *labibb)
|
|||
return rc;
|
||||
}
|
||||
|
||||
val = IBB_ENABLE_CTL_SWIRE_RDY;
|
||||
rc = qpnp_labibb_write(labibb, labibb->ibb_base + REG_IBB_ENABLE_CTL,
|
||||
&val, 1);
|
||||
rc = qpnp_ibb_set_mode(labibb, IBB_HW_CONTROL);
|
||||
if (rc) {
|
||||
pr_err("qpnp_labibb_write register %x failed rc = %d\n",
|
||||
REG_IBB_ENABLE_CTL, rc);
|
||||
pr_err("Unable to set SWIRE_RDY rc = %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
labibb->in_ttw_mode = true;
|
||||
|
@ -1072,16 +1102,6 @@ static int qpnp_labibb_regulator_ttw_mode_exit(struct qpnp_labibb *labibb)
|
|||
return rc;
|
||||
}
|
||||
|
||||
val = 0;
|
||||
rc = qpnp_labibb_write(labibb, labibb->ibb_base + REG_IBB_ENABLE_CTL,
|
||||
&val, 1);
|
||||
|
||||
if (rc) {
|
||||
pr_err("qpnp_labibb_write register %x failed rc = %d\n",
|
||||
REG_IBB_ENABLE_CTL, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
labibb->in_ttw_mode = false;
|
||||
return rc;
|
||||
}
|
||||
|
@ -1089,7 +1109,7 @@ static int qpnp_labibb_regulator_ttw_mode_exit(struct qpnp_labibb *labibb)
|
|||
static int qpnp_labibb_regulator_enable(struct qpnp_labibb *labibb)
|
||||
{
|
||||
int rc;
|
||||
u8 val = IBB_ENABLE_CTL_MODULE_EN;
|
||||
u8 val;
|
||||
int dly;
|
||||
int retries;
|
||||
bool enabled = false;
|
||||
|
@ -1103,12 +1123,9 @@ static int qpnp_labibb_regulator_enable(struct qpnp_labibb *labibb)
|
|||
}
|
||||
}
|
||||
|
||||
rc = qpnp_labibb_write(labibb, labibb->ibb_base + REG_IBB_ENABLE_CTL,
|
||||
&val, 1);
|
||||
|
||||
rc = qpnp_ibb_set_mode(labibb, IBB_SW_CONTROL_EN);
|
||||
if (rc) {
|
||||
pr_err("write register %x failed rc = %d\n",
|
||||
REG_IBB_ENABLE_CTL, rc);
|
||||
pr_err("Unable to set IBB_MODULE_EN rc = %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -1164,12 +1181,11 @@ static int qpnp_labibb_regulator_enable(struct qpnp_labibb *labibb)
|
|||
|
||||
return 0;
|
||||
err_out:
|
||||
val = 0;
|
||||
rc = qpnp_labibb_write(labibb, labibb->ibb_base + REG_IBB_ENABLE_CTL,
|
||||
&val, 1);
|
||||
if (rc)
|
||||
pr_err("write register %x failed rc = %d\n",
|
||||
REG_IBB_ENABLE_CTL, rc);
|
||||
rc = qpnp_ibb_set_mode(labibb, IBB_SW_CONTROL_DIS);
|
||||
if (rc) {
|
||||
pr_err("Unable to set IBB_MODULE_EN rc = %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -1181,12 +1197,28 @@ static int qpnp_labibb_regulator_disable(struct qpnp_labibb *labibb)
|
|||
int retries;
|
||||
bool disabled = false;
|
||||
|
||||
val = 0;
|
||||
rc = qpnp_labibb_write(labibb,
|
||||
labibb->ibb_base + REG_IBB_ENABLE_CTL, &val, 1);
|
||||
/*
|
||||
* When TTW mode is enabled and LABIBB regulators are disabled, it is
|
||||
* recommended not to disable IBB through IBB_ENABLE_CTL when switching
|
||||
* to SWIRE control on entering TTW mode. Hence, just enter TTW mode
|
||||
* and mark the regulators disabled. When we exit TTW mode, normal
|
||||
* mode settings will be restored anyways and regulators will be
|
||||
* enabled as before.
|
||||
*/
|
||||
if (labibb->ttw_en && !labibb->in_ttw_mode) {
|
||||
rc = qpnp_labibb_regulator_ttw_mode_enter(labibb);
|
||||
if (rc) {
|
||||
pr_err("Error in entering TTW mode rc = %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
labibb->lab_vreg.vreg_enabled = 0;
|
||||
labibb->ibb_vreg.vreg_enabled = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
rc = qpnp_ibb_set_mode(labibb, IBB_SW_CONTROL_DIS);
|
||||
if (rc) {
|
||||
pr_err("write register %x failed rc = %d\n",
|
||||
REG_IBB_ENABLE_CTL, rc);
|
||||
pr_err("Unable to set IBB_MODULE_EN rc = %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -1217,13 +1249,6 @@ static int qpnp_labibb_regulator_disable(struct qpnp_labibb *labibb)
|
|||
labibb->lab_vreg.vreg_enabled = 0;
|
||||
labibb->ibb_vreg.vreg_enabled = 0;
|
||||
|
||||
if (labibb->ttw_en && !labibb->in_ttw_mode) {
|
||||
rc = qpnp_labibb_regulator_ttw_mode_enter(labibb);
|
||||
if (rc) {
|
||||
pr_err("Error in entering TTW mode rc = %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2158,12 +2183,9 @@ static int qpnp_ibb_regulator_enable(struct regulator_dev *rdev)
|
|||
if (labibb->mode != QPNP_LABIBB_STANDALONE_MODE)
|
||||
return qpnp_labibb_regulator_enable(labibb);
|
||||
|
||||
val = IBB_ENABLE_CTL_MODULE_EN;
|
||||
rc = qpnp_labibb_write(labibb,
|
||||
labibb->ibb_base + REG_IBB_ENABLE_CTL, &val, 1);
|
||||
rc = qpnp_ibb_set_mode(labibb, IBB_SW_CONTROL_EN);
|
||||
if (rc) {
|
||||
pr_err("qpnp_ibb_regulator_enable write register %x failed rc = %d\n",
|
||||
REG_IBB_ENABLE_CTL, rc);
|
||||
pr_err("Unable to set IBB_MODULE_EN rc = %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -2190,7 +2212,6 @@ static int qpnp_ibb_regulator_enable(struct regulator_dev *rdev)
|
|||
static int qpnp_ibb_regulator_disable(struct regulator_dev *rdev)
|
||||
{
|
||||
int rc;
|
||||
u8 val;
|
||||
struct qpnp_labibb *labibb = rdev_get_drvdata(rdev);
|
||||
|
||||
if (labibb->ibb_vreg.vreg_enabled && !labibb->swire_control) {
|
||||
|
@ -2198,12 +2219,9 @@ static int qpnp_ibb_regulator_disable(struct regulator_dev *rdev)
|
|||
if (labibb->mode != QPNP_LABIBB_STANDALONE_MODE)
|
||||
return qpnp_labibb_regulator_disable(labibb);
|
||||
|
||||
val = 0;
|
||||
rc = qpnp_labibb_write(labibb, labibb->ibb_base +
|
||||
REG_IBB_ENABLE_CTL, &val, 1);
|
||||
rc = qpnp_ibb_set_mode(labibb, IBB_SW_CONTROL_DIS);
|
||||
if (rc) {
|
||||
pr_err("qpnp_ibb_regulator_enable write register %x failed rc = %d\n",
|
||||
REG_IBB_ENABLE_CTL, rc);
|
||||
pr_err("Unable to set IBB_MODULE_EN rc = %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue