summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnirudh Ghayal <aghayal@codeaurora.org>2016-05-03 22:34:07 +0530
committerKyle Yan <kyan@codeaurora.org>2016-06-17 15:19:54 -0700
commit3358aae86980e436b7ac7f507543297a7dd7e29c (patch)
tree3edcbe85c5ef13df5a46943509f7f672435e3afd
parenta492035331383753a1fc29ebb6ec4c3615ab13f1 (diff)
regulator: qpnp-labibb: Add support for controlling IBB pulse skip timing
The IBB pulse-skip and NLIMIT DAC configuration should be disabled before applying the 2nd SWIRE command skip logic, to guarantee that the IBB voltage changes immediately in the subsequent SWIRE command. After the WA is completed, the pulse-skip can be re-enabled after a programmable delay. Add this logic and a DT property 'qcom,swire-ibb-ps-enable-delay' to configure this delay. If this delay is not specified in the DT it defaults to 200ms. CRs-Fixed: 1010085 Change-Id: Ifec458a0028c16440ffd6ac1f6fa58eebc815c5a Signed-off-by: Anirudh Ghayal <aghayal@codeaurora.org>
-rw-r--r--Documentation/devicetree/bindings/regulator/qpnp-labibb-regulator.txt10
-rw-r--r--drivers/regulator/qpnp-labibb-regulator.c105
2 files changed, 62 insertions, 53 deletions
diff --git a/Documentation/devicetree/bindings/regulator/qpnp-labibb-regulator.txt b/Documentation/devicetree/bindings/regulator/qpnp-labibb-regulator.txt
index d3130efab1ec..7be400da0d62 100644
--- a/Documentation/devicetree/bindings/regulator/qpnp-labibb-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/qpnp-labibb-regulator.txt
@@ -33,11 +33,17 @@ Main node optional properties:
always on during TTW mode.
- qcom,skip-2nd-swire-cmd: A boolean property which indicates if
the second SWIRE command needs to be skipped.
-- qcom,swire-2nd-cmd-delay: A integer value which specifes the
+- qcom,swire-2nd-cmd-delay: An integer value which specifes the
delay in millisecs between the first and second
SWIRE command. If not specified this value
defaults to 20ms. This delay is applied only
- if 'qpnp,skip-2nd-swire-cmd' is defined.
+ if 'qcom,skip-2nd-swire-cmd' is defined.
+- qcom,swire-ibb-ps-enable-delay: An integer value which specifes the delay
+ in millisecs to enable IBB pulse-skipping
+ after the skip-2nd-swire-cmd workaround is applied.
+ If not specified this value default to 200ms.
+ This property is applicable only if
+ 'qcom,skip-2nd-swire-cmd' is specified.
- qcom,labibb-standalone: A boolean property which forces LAB and
IBB to operate in standalone mode. If
this is not specified, then LAB and IBB
diff --git a/drivers/regulator/qpnp-labibb-regulator.c b/drivers/regulator/qpnp-labibb-regulator.c
index 55ba6cfc25c2..2e41401f8580 100644
--- a/drivers/regulator/qpnp-labibb-regulator.c
+++ b/drivers/regulator/qpnp-labibb-regulator.c
@@ -250,7 +250,8 @@
#define IBB_WAIT_MBG_OK BIT(2)
/* Constants */
-#define SWIRE_DEFAULT_2ND_CMD_DLY_MS 20
+#define SWIRE_DEFAULT_2ND_CMD_DLY_MS 20
+#define SWIRE_DEFAULT_IBB_PS_ENABLE_DLY_MS 200
enum pmic_subtype {
PMI8994 = 10,
@@ -487,6 +488,7 @@ struct qpnp_labibb {
bool ttw_force_lab_on;
bool skip_2nd_swire_cmd;
u32 swire_2nd_cmd_delay;
+ u32 swire_ibb_ps_enable_delay;
};
enum ibb_settings_index {
@@ -677,6 +679,29 @@ static int qpnp_ibb_set_mode(struct qpnp_labibb *labibb, enum ibb_mode mode)
return rc;
}
+static int qpnp_ibb_ps_config(struct qpnp_labibb *labibb, bool enable)
+{
+ u8 val;
+ int rc;
+
+ val = enable ? IBB_PS_CTL_EN : IBB_PS_CTL_DISABLE;
+ rc = qpnp_labibb_write(labibb, labibb->ibb_base + REG_IBB_PS_CTL,
+ &val, 1);
+ if (rc) {
+ pr_err("qpnp_ibb_ps_config write register %x failed rc = %d\n",
+ REG_IBB_PS_CTL, rc);
+ return rc;
+ }
+
+ val = enable ? IBB_NLIMIT_DAC_EN : IBB_NLIMIT_DAC_DISABLE;
+ rc = qpnp_labibb_write(labibb, labibb->ibb_base + REG_IBB_NLIMIT_DAC,
+ &val, 1);
+ if (rc)
+ pr_err("qpnp_ibb_ps_config write register %x failed rc = %d\n",
+ REG_IBB_NLIMIT_DAC, rc);
+ return rc;
+}
+
static int qpnp_lab_dt_init(struct qpnp_labibb *labibb,
struct device_node *of_node)
{
@@ -1057,21 +1082,9 @@ static int qpnp_labibb_ttw_enter_ibb_pmi8950(struct qpnp_labibb *labibb)
int rc;
u8 val;
- val = 0;
- rc = qpnp_labibb_write(labibb, labibb->ibb_base + REG_IBB_NLIMIT_DAC,
- &val, 1);
+ rc = qpnp_ibb_ps_config(labibb, true);
if (rc) {
- pr_err("qpnp_labibb_write register %x failed rc = %d\n",
- REG_IBB_NLIMIT_DAC, rc);
- return rc;
- }
-
- val = IBB_PS_CTL_EN;
- rc = qpnp_labibb_write(labibb, labibb->ibb_base + REG_IBB_PS_CTL,
- &val, 1);
- if (rc) {
- pr_err("qpnp_labibb_write register %x failed rc = %d\n",
- REG_IBB_PS_CTL, rc);
+ pr_err("Failed to enable ibb_ps_config rc=%d\n", rc);
return rc;
}
@@ -1437,6 +1450,14 @@ static int qpnp_lab_regulator_enable(struct regulator_dev *rdev)
struct qpnp_labibb *labibb = rdev_get_drvdata(rdev);
+ if (labibb->skip_2nd_swire_cmd) {
+ rc = qpnp_ibb_ps_config(labibb, false);
+ if (rc) {
+ pr_err("Failed to disable IBB PS rc=%d\n", rc);
+ return rc;
+ }
+ }
+
if (!labibb->lab_vreg.vreg_enabled && !labibb->swire_control) {
if (!labibb->standalone)
@@ -1611,6 +1632,12 @@ static int qpnp_skip_swire_command(struct qpnp_labibb *labibb)
if (rc)
pr_err("Failed switch to IBB_HW_CONTROL rc=%d\n", rc);
+ /* delay before enabling the PS mode */
+ msleep(labibb->swire_ibb_ps_enable_delay);
+ rc = qpnp_ibb_ps_config(labibb, true);
+ if (rc)
+ pr_err("Unable to enable IBB PS rc=%d\n", rc);
+
return rc;
}
@@ -2120,47 +2147,16 @@ static int qpnp_ibb_dt_init(struct qpnp_labibb *labibb,
}
if (of_property_read_bool(of_node, "qcom,qpnp-ibb-ps-enable")) {
- val = IBB_PS_CTL_EN;
- rc = qpnp_labibb_write(labibb, labibb->ibb_base +
- REG_IBB_PS_CTL,
- &val,
- 1);
+ rc = qpnp_ibb_ps_config(labibb, true);
if (rc) {
- pr_err("qpnp_ibb_dt_init write register %x failed rc = %d\n",
- REG_IBB_PS_CTL, rc);
- return rc;
- }
-
- val = IBB_NLIMIT_DAC_EN;
- rc = qpnp_labibb_write(labibb, labibb->ibb_base +
- REG_IBB_NLIMIT_DAC,
- &val,
- 1);
- if (rc) {
- pr_err("qpnp_ibb_dt_init write register %x failed rc = %d\n",
- REG_IBB_NLIMIT_DAC, rc);
+ pr_err("qpnp_ibb_dt_init PS enable failed rc=%d\n", rc);
return rc;
}
} else {
- val = IBB_PS_CTL_DISABLE;
- rc = qpnp_labibb_write(labibb, labibb->ibb_base +
- REG_IBB_PS_CTL,
- &val,
- 1);
+ rc = qpnp_ibb_ps_config(labibb, false);
if (rc) {
- pr_err("qpnp_ibb_dt_init write register %x failed rc = %d\n",
- REG_IBB_PS_CTL, rc);
- return rc;
- }
-
- val = IBB_NLIMIT_DAC_DISABLE;
- rc = qpnp_labibb_write(labibb, labibb->ibb_base +
- REG_IBB_NLIMIT_DAC,
- &val,
- 1);
- if (rc) {
- pr_err("qpnp_ibb_dt_init write register %x failed rc = %d\n",
- REG_IBB_NLIMIT_DAC, rc);
+ pr_err("qpnp_ibb_dt_init PS disable failed rc=%d\n",
+ rc);
return rc;
}
}
@@ -2802,6 +2798,13 @@ static int qpnp_labibb_regulator_probe(struct platform_device *pdev)
if (rc)
labibb->swire_2nd_cmd_delay =
SWIRE_DEFAULT_2ND_CMD_DLY_MS;
+
+ rc = of_property_read_u32(labibb->dev->of_node,
+ "qcom,swire-ibb-ps-enable-delay",
+ &labibb->swire_ibb_ps_enable_delay);
+ if (rc)
+ labibb->swire_ibb_ps_enable_delay =
+ SWIRE_DEFAULT_IBB_PS_ENABLE_DLY_MS;
}
if (of_get_available_child_count(pdev->dev.of_node) == 0) {