summaryrefslogtreecommitdiff
path: root/drivers/regulator
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2017-04-19 19:27:26 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2017-04-19 19:27:26 -0700
commit7ca6c92e65d7e113068d5f555964d026ff847487 (patch)
tree1bf5622d0089323af6eda9bd12614c1f6aae901f /drivers/regulator
parent7514c164f1207f5596ce680c8dbf957e3b969133 (diff)
parent91a6162f195c0b79799cabc9d34b8785fc8df120 (diff)
Merge "regulator: qpnp-labibb: Handle LAB short circuit(SC) detection"
Diffstat (limited to 'drivers/regulator')
-rw-r--r--drivers/regulator/qpnp-labibb-regulator.c51
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);