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

Commit f81ad3ba authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "qcom: spmi-wled: Add support for OVP interrupt handling"

parents 76c0cfdc 4fb3309b
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -92,7 +92,7 @@ platforms. The PMIC is connected to the host processor via SPMI bus.
	Usage:      optional
	Value type: <string>
	Definition: Interrupt names associated with the interrupts.
		    Must be "sc-irq".
		    Currently supported interrupts are "sc-irq" and "ovp-irq".

Example:

@@ -102,8 +102,9 @@ qcom-wled@d800 {
	reg-names = "wled-ctrl-base", "wled-sink-base";
	label = "backlight";

	interrupts = <0x3 0xd8 0x2 IRQ_TYPE_EDGE_RISING>;
	interrupt-names = "sc-irq";
	interrupts = <0x3 0xd8 0x2 IRQ_TYPE_EDGE_RISING>,
			<0x3 0xd8 0x1 IRQ_TYPE_EDGE_RISING>;
	interrupt-names = "sc-irq", "ovp-irq";
	qcom,fs-current-limit = <25000>;
	qcom,current-boost-limit = <970>;
	qcom,switching-freq = <800>;
+84 −0
Original line number Diff line number Diff line
@@ -29,8 +29,15 @@
#define WLED_DEFAULT_BRIGHTNESS		2048
#define  WLED_MAX_BRIGHTNESS		4095

#define WLED_SOFT_START_DLY_US		10000

/* WLED control registers */
#define WLED_CTRL_FAULT_STATUS		0x08
#define  WLED_CTRL_ILIM_FAULT_BIT	BIT(0)
#define  WLED_CTRL_OVP_FAULT_BIT	BIT(1)
#define  WLED_CTRL_SC_FAULT_BIT		BIT(2)

#define WLED_CTRL_INT_RT_STS		0x10

#define WLED_CTRL_MOD_ENABLE		0x46
#define  WLED_CTRL_MOD_EN_MASK		BIT(7)
@@ -89,6 +96,7 @@ struct wled_config {
	u32 fs_current;
	u32 string_cfg;
	int sc_irq;
	int ovp_irq;
	bool en_cabc;
	bool ext_pfet_sc_pro_en;
};
@@ -105,6 +113,7 @@ struct wled {
	u32 brightness;
	u32 sc_count;
	bool prev_state;
	bool ovp_irq_disabled;
};

static int wled_module_enable(struct wled *wled, int val)
@@ -114,6 +123,28 @@ static int wled_module_enable(struct wled *wled, int val)
	rc = regmap_update_bits(wled->regmap, wled->ctrl_addr +
			WLED_CTRL_MOD_ENABLE, WLED_CTRL_MOD_EN_MASK,
			val << WLED_CTRL_MODULE_EN_SHIFT);
	if (rc < 0)
		return rc;
	/*
	 * Wait for at least 10ms before enabling OVP fault interrupt after
	 * enabling the module so that soft start is completed. Keep the OVP
	 * interrupt disabled when the module is disabled.
	 */
	if (val) {
		usleep_range(WLED_SOFT_START_DLY_US,
				WLED_SOFT_START_DLY_US + 1000);

		if (wled->cfg.ovp_irq > 0 && wled->ovp_irq_disabled) {
			enable_irq(wled->cfg.ovp_irq);
			wled->ovp_irq_disabled = false;
		}
	} else {
		if (wled->cfg.ovp_irq > 0 && !wled->ovp_irq_disabled) {
			disable_irq(wled->cfg.ovp_irq);
			wled->ovp_irq_disabled = true;
		}
	}

	return rc;
}

@@ -266,12 +297,42 @@ static irqreturn_t wled_sc_irq_handler(int irq, void *_wled)
	return IRQ_HANDLED;
}

static irqreturn_t wled_ovp_irq_handler(int irq, void *_wled)
{
	struct wled *wled = _wled;
	int rc;
	u32 int_sts, fault_sts;

	rc = regmap_read(wled->regmap,
			wled->ctrl_addr + WLED_CTRL_INT_RT_STS, &int_sts);
	if (rc < 0) {
		pr_err("Error in reading WLED_INT_RT_STS rc=%d\n", rc);
		return IRQ_HANDLED;
	}

	rc = regmap_read(wled->regmap, wled->ctrl_addr +
			WLED_CTRL_FAULT_STATUS, &fault_sts);
	if (rc < 0) {
		pr_err("Error in reading WLED_FAULT_STATUS rc=%d\n", rc);
		return IRQ_HANDLED;
	}

	if (fault_sts &
		(WLED_CTRL_OVP_FAULT_BIT | WLED_CTRL_ILIM_FAULT_BIT))
		pr_err("WLED OVP fault detected, int_sts=%x fault_sts= %x\n",
			int_sts, fault_sts);

	return IRQ_HANDLED;
}

static int wled_setup(struct wled *wled)
{
	int rc, temp, i;
	u8 sink_en = 0;
	u32 val;
	u8 string_cfg = wled->cfg.string_cfg;
	int sc_irq = wled->cfg.sc_irq;
	int ovp_irq = wled->cfg.ovp_irq;

	rc = regmap_update_bits(wled->regmap,
			wled->ctrl_addr + WLED_CTRL_OVP,
@@ -369,6 +430,25 @@ static int wled_setup(struct wled *wled)
			return rc;
	}

	if (ovp_irq >= 0) {
		rc = devm_request_threaded_irq(&wled->pdev->dev, ovp_irq,
				NULL, wled_ovp_irq_handler, IRQF_ONESHOT,
				"wled_ovp_irq", wled);
		if (rc < 0) {
			dev_err(&wled->pdev->dev, "Unable to request ovp(%d) IRQ(err:%d)\n",
				ovp_irq, rc);
			return rc;
		}

		rc = regmap_read(wled->regmap, wled->ctrl_addr +
				WLED_CTRL_MOD_ENABLE, &val);
		/* disable the OVP irq only if the module is not enabled */
		if (!rc && !(val & WLED_CTRL_MOD_EN_MASK)) {
			disable_irq(ovp_irq);
			wled->ovp_irq_disabled = true;
		}
	}

	return 0;
}

@@ -541,6 +621,10 @@ static int wled_configure(struct wled *wled, struct device *dev)
	if (wled->cfg.sc_irq < 0)
		dev_dbg(&wled->pdev->dev, "sc irq is not used\n");

	wled->cfg.ovp_irq = platform_get_irq_byname(wled->pdev, "ovp-irq");
	if (wled->cfg.ovp_irq < 0)
		dev_dbg(&wled->pdev->dev, "ovp irq is not used\n");

	return 0;
}