regulator: qpnp-labibb: Handle LAB short circuit(SC) detection
On certain PMICs, there is no short circuit (SC) detection available in LAB module. Add support to detect it manually and disable LAB/IBB module upon SC detection. In addition, notify it to OLEDB driver to disable OLEDB module. Change-Id: I2a9dc5b1ae8ece45c85b3992026c7f389fd4d135 Signed-off-by: Kiran Gunda <kgunda@codeaurora.org>
This commit is contained in:
parent
7f0d77b390
commit
91a6162f19
3 changed files with 52 additions and 4 deletions
|
@ -151,6 +151,10 @@ LAB subnode optional properties:
|
|||
any value in the allowed limit.
|
||||
- qcom,notify-lab-vreg-ok-sts: A boolean property which upon set will
|
||||
poll and notify the lab_vreg_ok status.
|
||||
- qcom,qpnp-lab-sc-wait-time-ms: This property is used to specify the time
|
||||
(in ms) to poll for the short circuit
|
||||
detection. If not specified the default time
|
||||
is 5 sec.
|
||||
|
||||
Following properties are available only for PM660A:
|
||||
|
||||
|
|
|
@ -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,11 +2160,31 @@ static void qpnp_lab_vreg_notifier_work(struct work_struct *work)
|
|||
}
|
||||
|
||||
usleep_range(dly, dly + 100);
|
||||
retries--;
|
||||
}
|
||||
|
||||
if (!retries)
|
||||
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);
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
enum labibb_notify_event {
|
||||
LAB_VREG_OK = 1,
|
||||
LAB_VREG_NOT_OK,
|
||||
};
|
||||
|
||||
int qpnp_labibb_notifier_register(struct notifier_block *nb);
|
||||
|
|
Loading…
Add table
Reference in a new issue