regulator: qpnp-lcdb: Add a DT property for LDO power-down delay
Add "qcom,pwrdn-delay-ms" device tree property to meet the power
down delay spec for few display panels. Also, enable force-pull
down on module disable to do a quick discharge of the LDO.
Change-Id: I07d55cdbfe3b253579ca3722fc02604a4a7483e0
Signed-off-by: Kiran Gunda <kgunda@codeaurora.org>
diff --git a/drivers/regulator/qpnp-lcdb-regulator.c b/drivers/regulator/qpnp-lcdb-regulator.c
index 0fd7802..744e35a 100644
--- a/drivers/regulator/qpnp-lcdb-regulator.c
+++ b/drivers/regulator/qpnp-lcdb-regulator.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2019, 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
@@ -114,6 +114,10 @@
#define PFM_CURRENT_SHIFT 2
#define LCDB_PWRUP_PWRDN_CTL_REG 0x66
+#define PWRUP_DELAY_MASK GENAMSK(3, 2)
+#define PWRDN_DELAY_MASK GENMASK(1, 0)
+#define PWRDN_DELAY_MIN_MS 0
+#define PWRDN_DELAY_MAX_MS 8
/* LDO */
#define LCDB_LDO_OUTPUT_VOLTAGE_REG 0x71
@@ -126,6 +130,10 @@
#define LDO_DIS_PULLDOWN_BIT BIT(1)
#define LDO_PD_STRENGTH_BIT BIT(0)
+#define LCDB_LDO_FORCE_PD_CTL_REG 0x79
+#define LDO_FORCE_PD_EN_BIT BIT(0)
+#define LDO_FORCE_PD_MODE BIT(7)
+
#define LCDB_LDO_ILIM_CTL1_REG 0x7B
#define EN_LDO_ILIM_BIT BIT(7)
#define SET_LDO_ILIM_MASK GENMASK(2, 0)
@@ -223,6 +231,7 @@
u32 base;
u32 wa_flags;
int sc_irq;
+ int pwrdn_delay_ms;
/* TTW params */
bool ttw_enable;
@@ -297,6 +306,7 @@
enum lcdb_wa_flags {
NCP_SCP_DISABLE_WA = BIT(0),
+ FORCE_PD_ENABLE_WA = BIT(1),
};
static u32 soft_start_us[] = {
@@ -320,6 +330,13 @@
810,
};
+static const u32 pwrup_pwrdn_ms[] = {
+ 0,
+ 1,
+ 4,
+ 8,
+};
+
#define SETTING(_id, _sec_access, _valid) \
[_id] = { \
.address = _id##_REG, \
@@ -922,6 +939,18 @@
return 0;
}
+ if (lcdb->wa_flags & FORCE_PD_ENABLE_WA) {
+ /*
+ * force pull-down to enable quick discharge after
+ * turning off
+ */
+ val = LDO_FORCE_PD_EN_BIT | LDO_FORCE_PD_MODE;
+ rc = qpnp_lcdb_write(lcdb, lcdb->base +
+ LCDB_LDO_FORCE_PD_CTL_REG, &val, 1);
+ if (rc < 0)
+ return rc;
+ }
+
val = 0;
rc = qpnp_lcdb_write(lcdb, lcdb->base + LCDB_ENABLE_CTL1_REG,
&val, 1);
@@ -930,6 +959,17 @@
else
lcdb->lcdb_enabled = false;
+ if (lcdb->wa_flags & FORCE_PD_ENABLE_WA) {
+ /* wait for 10 msec after module disable for LDO to discharge */
+ usleep_range(10000, 11000);
+
+ val = 0;
+ rc = qpnp_lcdb_write(lcdb, lcdb->base +
+ LCDB_LDO_FORCE_PD_CTL_REG, &val, 1);
+ if (rc < 0)
+ return rc;
+ }
+
return rc;
}
@@ -2052,6 +2092,10 @@
if (lcdb->pmic_rev_id->rev4 < PM660L_V2P0_REV4)
lcdb->wa_flags |= NCP_SCP_DISABLE_WA;
break;
+ case PMI632_SUBTYPE:
+ case PM855L_SUBTYPE:
+ lcdb->wa_flags |= FORCE_PD_ENABLE_WA;
+ break;
default:
break;
}
@@ -2066,6 +2110,15 @@
qpnp_lcdb_pmic_config(lcdb);
+ if (lcdb->pwrdn_delay_ms != -EINVAL) {
+ rc = qpnp_lcdb_masked_write(lcdb, lcdb->base +
+ LCDB_PWRUP_PWRDN_CTL_REG,
+ PWRDN_DELAY_MASK,
+ lcdb->pwrdn_delay_ms);
+ if (rc < 0)
+ return rc;
+ }
+
rc = qpnp_lcdb_init_bst(lcdb);
if (rc < 0) {
pr_err("Failed to initialize BOOST rc=%d\n", rc);
@@ -2124,7 +2177,8 @@
static int qpnp_lcdb_parse_dt(struct qpnp_lcdb *lcdb)
{
- int rc = 0;
+ int rc = 0, i = 0;
+ u32 tmp;
const char *label;
struct device_node *revid_dev_node, *temp, *node = lcdb->dev->of_node;
@@ -2189,7 +2243,24 @@
lcdb->voltage_step_ramp =
of_property_read_bool(node, "qcom,voltage-step-ramp");
- return rc;
+ lcdb->pwrdn_delay_ms = -EINVAL;
+ rc = of_property_read_u32(node, "qcom,pwrdn-delay-ms", &tmp);
+ if (!rc) {
+ if (!is_between(tmp, PWRDN_DELAY_MIN_MS, PWRDN_DELAY_MAX_MS)) {
+ pr_err("Invalid PWRDN_DLY val %d (min=%d max=%d)\n",
+ tmp, PWRDN_DELAY_MIN_MS, PWRDN_DELAY_MAX_MS);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(pwrup_pwrdn_ms); i++) {
+ if (tmp == pwrup_pwrdn_ms[i]) {
+ lcdb->pwrdn_delay_ms = i;
+ break;
+ }
+ }
+ }
+
+ return 0;
}
static ssize_t qpnp_lcdb_irq_control(struct class *c,