Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 91a6162f authored by Kiran Gunda's avatar Kiran Gunda
Browse files

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: default avatarKiran Gunda <kgunda@codeaurora.org>
parent 7f0d77b3
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -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:

+47 −4
Original line number Diff line number Diff line
@@ -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);
+1 −0
Original line number Diff line number Diff line
@@ -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);