Merge "regulator: qpnp-lcdb: Add a WA to toggle SC before module_enable"

This commit is contained in:
Linux Build Service Account 2017-04-03 06:24:45 -07:00 committed by Gerrit - the friendly Code Review server
commit 46b41403c3
4 changed files with 98 additions and 33 deletions

View file

@ -26,12 +26,10 @@ First Level Node - LCDB module
Value type: <prop-encoded-array> Value type: <prop-encoded-array>
Definition: Base address of the LCDB SPMI peripheral. Definition: Base address of the LCDB SPMI peripheral.
- qcom,force-module-reenable - qcom,pmic-revid
Usage: required if using SW mode for module enable Usage: required
Value type: <bool> Value type: <phandle>
Definition: This enables the workaround to force enable Definition: Phandle to the PMIC's revid node
the vph_pwr_2p5_ok signal required for
turning on the LCDB module.
Touch-to-wake (TTW) properties: Touch-to-wake (TTW) properties:

View file

@ -397,7 +397,7 @@
interrupts = <0x3 0xec 0x1 IRQ_TYPE_EDGE_RISING>; interrupts = <0x3 0xec 0x1 IRQ_TYPE_EDGE_RISING>;
interrupt-names = "sc-irq"; interrupt-names = "sc-irq";
qcom,force-module-reenable; qcom,pmic-revid = <&pm660l_revid>;
lcdb_ldo_vreg: ldo { lcdb_ldo_vreg: ldo {
label = "ldo"; label = "ldo";

View file

@ -24,6 +24,7 @@
#include <linux/regulator/driver.h> #include <linux/regulator/driver.h>
#include <linux/regulator/of_regulator.h> #include <linux/regulator/of_regulator.h>
#include <linux/regulator/machine.h> #include <linux/regulator/machine.h>
#include <linux/qpnp/qpnp-revid.h>
#define QPNP_LCDB_REGULATOR_DRIVER_NAME "qcom,qpnp-lcdb-regulator" #define QPNP_LCDB_REGULATOR_DRIVER_NAME "qcom,qpnp-lcdb-regulator"
@ -192,6 +193,7 @@ struct qpnp_lcdb {
struct device *dev; struct device *dev;
struct platform_device *pdev; struct platform_device *pdev;
struct regmap *regmap; struct regmap *regmap;
struct pmic_revid_data *pmic_rev_id;
u32 base; u32 base;
int sc_irq; int sc_irq;
@ -199,9 +201,6 @@ struct qpnp_lcdb {
bool ttw_enable; bool ttw_enable;
bool ttw_mode_sw; bool ttw_mode_sw;
/* top level DT params */
bool force_module_reenable;
/* status parameters */ /* status parameters */
bool lcdb_enabled; bool lcdb_enabled;
bool settings_saved; bool settings_saved;
@ -579,6 +578,65 @@ static int qpnp_lcdb_ttw_exit(struct qpnp_lcdb *lcdb)
return 0; return 0;
} }
static int qpnp_lcdb_enable_wa(struct qpnp_lcdb *lcdb)
{
int rc;
u8 val = 0;
/* required only for PM660L */
if (lcdb->pmic_rev_id->pmic_subtype != PM660L_SUBTYPE)
return 0;
val = MODULE_EN_BIT;
rc = qpnp_lcdb_write(lcdb, lcdb->base + LCDB_ENABLE_CTL1_REG,
&val, 1);
if (rc < 0) {
pr_err("Failed to enable lcdb rc= %d\n", rc);
return rc;
}
val = 0;
rc = qpnp_lcdb_write(lcdb, lcdb->base + LCDB_ENABLE_CTL1_REG,
&val, 1);
if (rc < 0) {
pr_err("Failed to disable lcdb rc= %d\n", rc);
return rc;
}
/* execute the below for rev1.1 */
if (lcdb->pmic_rev_id->rev3 == PM660L_V1P1_REV3 &&
lcdb->pmic_rev_id->rev4 == PM660L_V1P1_REV4) {
/*
* delay to make sure that the MID pin ie the
* output of the LCDB boost returns to 0V
* after the module is disabled
*/
usleep_range(10000, 10100);
rc = qpnp_lcdb_masked_write(lcdb,
lcdb->base + LCDB_MISC_CTL_REG,
DIS_SCP_BIT, DIS_SCP_BIT);
if (rc < 0) {
pr_err("Failed to disable SC rc=%d\n", rc);
return rc;
}
/* delay for SC-disable to take effect */
usleep_range(1000, 1100);
rc = qpnp_lcdb_masked_write(lcdb,
lcdb->base + LCDB_MISC_CTL_REG,
DIS_SCP_BIT, 0);
if (rc < 0) {
pr_err("Failed to enable SC rc=%d\n", rc);
return rc;
}
/* delay for SC-enable to take effect */
usleep_range(1000, 1100);
}
return 0;
}
static int qpnp_lcdb_enable(struct qpnp_lcdb *lcdb) static int qpnp_lcdb_enable(struct qpnp_lcdb *lcdb)
{ {
int rc = 0, timeout, delay; int rc = 0, timeout, delay;
@ -598,22 +656,12 @@ static int qpnp_lcdb_enable(struct qpnp_lcdb *lcdb)
} }
} }
val = MODULE_EN_BIT; rc = qpnp_lcdb_enable_wa(lcdb);
rc = qpnp_lcdb_write(lcdb, lcdb->base + LCDB_ENABLE_CTL1_REG,
&val, 1);
if (rc < 0) { if (rc < 0) {
pr_err("Failed to enable lcdb rc= %d\n", rc); pr_err("Failed to execute enable_wa rc=%d\n", rc);
goto fail_enable; return rc;
} }
if (lcdb->force_module_reenable) {
val = 0;
rc = qpnp_lcdb_write(lcdb, lcdb->base + LCDB_ENABLE_CTL1_REG,
&val, 1);
if (rc < 0) {
pr_err("Failed to enable lcdb rc= %d\n", rc);
goto fail_enable;
}
val = MODULE_EN_BIT; val = MODULE_EN_BIT;
rc = qpnp_lcdb_write(lcdb, lcdb->base + LCDB_ENABLE_CTL1_REG, rc = qpnp_lcdb_write(lcdb, lcdb->base + LCDB_ENABLE_CTL1_REG,
&val, 1); &val, 1);
@ -621,7 +669,6 @@ static int qpnp_lcdb_enable(struct qpnp_lcdb *lcdb)
pr_err("Failed to disable lcdb rc= %d\n", rc); pr_err("Failed to disable lcdb rc= %d\n", rc);
goto fail_enable; goto fail_enable;
} }
}
/* poll for vreg_ok */ /* poll for vreg_ok */
timeout = 10; timeout = 10;
@ -1674,7 +1721,8 @@ static int qpnp_lcdb_hw_init(struct qpnp_lcdb *lcdb)
return rc; return rc;
} }
if (lcdb->sc_irq >= 0) { if (lcdb->sc_irq >= 0 &&
lcdb->pmic_rev_id->pmic_subtype != PM660L_SUBTYPE) {
lcdb->sc_count = 0; lcdb->sc_count = 0;
rc = devm_request_threaded_irq(lcdb->dev, lcdb->sc_irq, rc = devm_request_threaded_irq(lcdb->dev, lcdb->sc_irq,
NULL, qpnp_lcdb_sc_irq_handler, IRQF_ONESHOT, NULL, qpnp_lcdb_sc_irq_handler, IRQF_ONESHOT,
@ -1714,7 +1762,23 @@ static int qpnp_lcdb_parse_dt(struct qpnp_lcdb *lcdb)
{ {
int rc = 0; int rc = 0;
const char *label; const char *label;
struct device_node *temp, *node = lcdb->dev->of_node; struct device_node *revid_dev_node, *temp, *node = lcdb->dev->of_node;
revid_dev_node = of_parse_phandle(node, "qcom,pmic-revid", 0);
if (!revid_dev_node) {
pr_err("Missing qcom,pmic-revid property - fail driver\n");
return -EINVAL;
}
lcdb->pmic_rev_id = get_revid_data(revid_dev_node);
if (IS_ERR(lcdb->pmic_rev_id)) {
pr_debug("Unable to get revid data\n");
/*
* revid should to be defined, return -EPROBE_DEFER
* until the revid module registers.
*/
return -EPROBE_DEFER;
}
for_each_available_child_of_node(node, temp) { for_each_available_child_of_node(node, temp) {
rc = of_property_read_string(temp, "label", &label); rc = of_property_read_string(temp, "label", &label);
@ -1742,9 +1806,6 @@ static int qpnp_lcdb_parse_dt(struct qpnp_lcdb *lcdb)
} }
} }
lcdb->force_module_reenable = of_property_read_bool(node,
"qcom,force-module-reenable");
if (of_property_read_bool(node, "qcom,ttw-enable")) { if (of_property_read_bool(node, "qcom,ttw-enable")) {
rc = qpnp_lcdb_parse_ttw(lcdb); rc = qpnp_lcdb_parse_ttw(lcdb);
if (rc < 0) { if (rc < 0) {

View file

@ -208,6 +208,12 @@
#define PM660_V1P1_REV3 0x01 #define PM660_V1P1_REV3 0x01
#define PM660_V1P1_REV4 0x01 #define PM660_V1P1_REV4 0x01
/* PM660L REV_ID */
#define PM660L_V1P1_REV1 0x00
#define PM660L_V1P1_REV2 0x00
#define PM660L_V1P1_REV3 0x01
#define PM660L_V1P1_REV4 0x01
/* PMI8998 FAB_ID */ /* PMI8998 FAB_ID */
#define PMI8998_FAB_ID_SMIC 0x11 #define PMI8998_FAB_ID_SMIC 0x11
#define PMI8998_FAB_ID_GF 0x30 #define PMI8998_FAB_ID_GF 0x30