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) {