diff --git a/Documentation/devicetree/bindings/regulator/qpnp-lcdb-regulator.txt b/Documentation/devicetree/bindings/regulator/qpnp-lcdb-regulator.txt index 63da8ecbfa4c..ed383ce9ea8f 100644 --- a/Documentation/devicetree/bindings/regulator/qpnp-lcdb-regulator.txt +++ b/Documentation/devicetree/bindings/regulator/qpnp-lcdb-regulator.txt @@ -26,12 +26,10 @@ First Level Node - LCDB module Value type: Definition: Base address of the LCDB SPMI peripheral. -- qcom,force-module-reenable - Usage: required if using SW mode for module enable - Value type: - Definition: This enables the workaround to force enable - the vph_pwr_2p5_ok signal required for - turning on the LCDB module. +- qcom,pmic-revid + Usage: required + Value type: + Definition: Phandle to the PMIC's revid node Touch-to-wake (TTW) properties: diff --git a/arch/arm/boot/dts/qcom/msm-pm660l.dtsi b/arch/arm/boot/dts/qcom/msm-pm660l.dtsi index bcdbc4ed7c55..7f386957d555 100644 --- a/arch/arm/boot/dts/qcom/msm-pm660l.dtsi +++ b/arch/arm/boot/dts/qcom/msm-pm660l.dtsi @@ -397,7 +397,7 @@ interrupts = <0x3 0xec 0x1 IRQ_TYPE_EDGE_RISING>; interrupt-names = "sc-irq"; - qcom,force-module-reenable; + qcom,pmic-revid = <&pm660l_revid>; lcdb_ldo_vreg: ldo { label = "ldo"; diff --git a/drivers/regulator/qpnp-lcdb-regulator.c b/drivers/regulator/qpnp-lcdb-regulator.c index aef28dbeb931..724e8a4c00da 100644 --- a/drivers/regulator/qpnp-lcdb-regulator.c +++ b/drivers/regulator/qpnp-lcdb-regulator.c @@ -24,6 +24,7 @@ #include #include #include +#include #define QPNP_LCDB_REGULATOR_DRIVER_NAME "qcom,qpnp-lcdb-regulator" @@ -192,6 +193,7 @@ struct qpnp_lcdb { struct device *dev; struct platform_device *pdev; struct regmap *regmap; + struct pmic_revid_data *pmic_rev_id; u32 base; int sc_irq; @@ -199,9 +201,6 @@ struct qpnp_lcdb { bool ttw_enable; bool ttw_mode_sw; - /* top level DT params */ - bool force_module_reenable; - /* status parameters */ bool lcdb_enabled; bool settings_saved; @@ -579,6 +578,65 @@ static int qpnp_lcdb_ttw_exit(struct qpnp_lcdb *lcdb) 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) { int rc = 0, timeout, delay; @@ -598,31 +656,20 @@ static int qpnp_lcdb_enable(struct qpnp_lcdb *lcdb) } } + rc = qpnp_lcdb_enable_wa(lcdb); + if (rc < 0) { + pr_err("Failed to execute enable_wa rc=%d\n", rc); + return rc; + } + 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); + pr_err("Failed to disable lcdb rc= %d\n", rc); goto fail_enable; } - 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; - 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); - goto fail_enable; - } - } - /* poll for vreg_ok */ timeout = 10; delay = lcdb->bst.soft_start_us + lcdb->ldo.soft_start_us + @@ -1674,7 +1721,8 @@ static int qpnp_lcdb_hw_init(struct qpnp_lcdb *lcdb) return rc; } - if (lcdb->sc_irq >= 0) { + if (lcdb->sc_irq >= 0 && + lcdb->pmic_rev_id->pmic_subtype != PM660L_SUBTYPE) { lcdb->sc_count = 0; rc = devm_request_threaded_irq(lcdb->dev, lcdb->sc_irq, 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; 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) { 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")) { rc = qpnp_lcdb_parse_ttw(lcdb); if (rc < 0) { diff --git a/include/linux/qpnp/qpnp-revid.h b/include/linux/qpnp/qpnp-revid.h index a0e2283ef4c9..7254f4d16176 100644 --- a/include/linux/qpnp/qpnp-revid.h +++ b/include/linux/qpnp/qpnp-revid.h @@ -208,6 +208,12 @@ #define PM660_V1P1_REV3 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 */ #define PMI8998_FAB_ID_SMIC 0x11 #define PMI8998_FAB_ID_GF 0x30