diff options
| author | Linux Build Service Account <lnxbuild@localhost> | 2017-04-19 19:27:26 -0700 |
|---|---|---|
| committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2017-04-19 19:27:26 -0700 |
| commit | 7ca6c92e65d7e113068d5f555964d026ff847487 (patch) | |
| tree | 1bf5622d0089323af6eda9bd12614c1f6aae901f /drivers/regulator | |
| parent | 7514c164f1207f5596ce680c8dbf957e3b969133 (diff) | |
| parent | 91a6162f195c0b79799cabc9d34b8785fc8df120 (diff) | |
Merge "regulator: qpnp-labibb: Handle LAB short circuit(SC) detection"
Diffstat (limited to 'drivers/regulator')
| -rw-r--r-- | drivers/regulator/qpnp-labibb-regulator.c | 51 |
1 files changed, 47 insertions, 4 deletions
diff --git a/drivers/regulator/qpnp-labibb-regulator.c b/drivers/regulator/qpnp-labibb-regulator.c index dbe2a08f1776..858ddcc228df 100644 --- a/drivers/regulator/qpnp-labibb-regulator.c +++ b/drivers/regulator/qpnp-labibb-regulator.c @@ -559,6 +559,7 @@ struct lab_regulator { int step_size; int slew_rate; int soft_start; + int sc_wait_time_ms; int vreg_enabled; }; @@ -608,6 +609,8 @@ struct qpnp_labibb { bool skip_2nd_swire_cmd; bool pfm_enable; bool notify_lab_vreg_ok_sts; + bool detect_lab_sc; + bool sc_detected; u32 swire_2nd_cmd_delay; u32 swire_ibb_ps_enable_delay; }; @@ -2138,8 +2141,10 @@ static void qpnp_lab_vreg_notifier_work(struct work_struct *work) u8 val; struct qpnp_labibb *labibb = container_of(work, struct qpnp_labibb, lab_vreg_ok_work); + if (labibb->lab_vreg.sc_wait_time_ms != -EINVAL) + retries = labibb->lab_vreg.sc_wait_time_ms / 5; - while (retries--) { + while (retries) { rc = qpnp_labibb_read(labibb, labibb->lab_base + REG_LAB_STATUS1, &val, 1); if (rc < 0) { @@ -2155,10 +2160,30 @@ static void qpnp_lab_vreg_notifier_work(struct work_struct *work) } usleep_range(dly, dly + 100); + retries--; } - if (!retries) - pr_err("LAB_VREG_OK not set, failed to notify\n"); + if (!retries) { + if (labibb->detect_lab_sc) { + pr_crit("short circuit detected on LAB rail.. disabling the LAB/IBB/OLEDB modules\n"); + /* Disable LAB module */ + val = 0; + rc = qpnp_labibb_write(labibb, labibb->lab_base + + REG_LAB_MODULE_RDY, &val, 1); + if (rc < 0) { + pr_err("write register %x failed rc = %d\n", + REG_LAB_MODULE_RDY, rc); + return; + } + raw_notifier_call_chain(&labibb_notifier, + LAB_VREG_NOT_OK, NULL); + labibb->sc_detected = true; + labibb->lab_vreg.vreg_enabled = 0; + labibb->ibb_vreg.vreg_enabled = 0; + } else { + pr_err("LAB_VREG_OK not set, failed to notify\n"); + } + } } static int qpnp_labibb_regulator_enable(struct qpnp_labibb *labibb) @@ -2323,6 +2348,11 @@ static int qpnp_lab_regulator_enable(struct regulator_dev *rdev) struct qpnp_labibb *labibb = rdev_get_drvdata(rdev); + if (labibb->sc_detected) { + pr_info("Short circuit detected: disabled LAB/IBB rails\n"); + return 0; + } + if (labibb->skip_2nd_swire_cmd) { rc = qpnp_ibb_ps_config(labibb, false); if (rc < 0) { @@ -2363,7 +2393,7 @@ static int qpnp_lab_regulator_enable(struct regulator_dev *rdev) labibb->lab_vreg.vreg_enabled = 1; } - if (labibb->notify_lab_vreg_ok_sts) + if (labibb->notify_lab_vreg_ok_sts || labibb->detect_lab_sc) schedule_work(&labibb->lab_vreg_ok_work); return 0; @@ -2621,6 +2651,12 @@ static int register_qpnp_lab_regulator(struct qpnp_labibb *labibb, labibb->notify_lab_vreg_ok_sts = of_property_read_bool(of_node, "qcom,notify-lab-vreg-ok-sts"); + labibb->lab_vreg.sc_wait_time_ms = -EINVAL; + if (labibb->pmic_rev_id->pmic_subtype == PM660L_SUBTYPE && + labibb->detect_lab_sc) + of_property_read_u32(of_node, "qcom,qpnp-lab-sc-wait-time-ms", + &labibb->lab_vreg.sc_wait_time_ms); + rc = of_property_read_u32(of_node, "qcom,qpnp-lab-soft-start", &(labibb->lab_vreg.soft_start)); if (!rc) { @@ -3255,6 +3291,11 @@ static int qpnp_ibb_regulator_enable(struct regulator_dev *rdev) u8 val; struct qpnp_labibb *labibb = rdev_get_drvdata(rdev); + if (labibb->sc_detected) { + pr_info("Short circuit detected: disabled LAB/IBB rails\n"); + return 0; + } + if (!labibb->ibb_vreg.vreg_enabled && !labibb->swire_control) { if (!labibb->standalone) @@ -3731,6 +3772,8 @@ static int qpnp_labibb_regulator_probe(struct platform_device *pdev) if (labibb->pmic_rev_id->pmic_subtype == PM660L_SUBTYPE) { labibb->mode = QPNP_LABIBB_AMOLED_MODE; + /* Enable polling for LAB short circuit detection for PM660A */ + labibb->detect_lab_sc = true; } else { rc = of_property_read_string(labibb->dev->of_node, "qcom,qpnp-labibb-mode", &mode_name); |
