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

Commit b3ff3a62 authored by Xiaozhe Shi's avatar Xiaozhe Shi
Browse files

msm: qpnp-power-on: add support for handling pmic watchdog barks



PMIC watchdog resets are often very difficult to debug due to the sudden
shutdown of the system. Add support in the qpnp-power-on driver to
handle the pmic watch dog bark, log a message and panic so that the
reset reason is clear to testers.

Change-Id: I0b7f3f3780769a8260cce73ee8dce91200e8873a
Signed-off-by: default avatarXiaozhe Shi <xiaozhes@codeaurora.org>
parent aa3ebc17
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -16,7 +16,9 @@ Required properties:
			"kpdpwr-resin-bark". Bark interrupts are associated with system
			reset configuration to allow default reset configuration to be
			activated. If system reset configuration is not supported then
			bark interrupts are nops.
			bark interrupts are nops. Additionally, the "pmic-wd-bark"
			interrupt can be added if the system needs to handle PMIC
			watch dog barks.

Optional properties:
- qcom,pon-dbc-delay		The debounce delay for the power-key interrupt
+64 −1
Original line number Diff line number Diff line
@@ -506,6 +506,54 @@ static irqreturn_t qpnp_cblpwr_irq(int irq, void *_pon)
	return IRQ_HANDLED;
}

static void print_pon_reg(struct qpnp_pon *pon, u16 offset)
{
	int rc;
	u16 addr;
	u8 reg;

	addr = pon->base + offset;
	rc = spmi_ext_register_readl(pon->spmi->ctrl, pon->spmi->sid,
			addr, &reg, 1);
	if (rc)
		dev_emerg(&pon->spmi->dev,
				"Unable to read reg at 0x%04x\n", addr);
	else
		dev_emerg(&pon->spmi->dev, "reg@0x%04x: %02x\n", addr, reg);
}

#define PON_PBL_STATUS			0x7
#define PON_PON_REASON1			0x8
#define PON_PON_REASON2			0x9
#define PON_WARM_RESET_REASON1		0xA
#define PON_WARM_RESET_REASON2		0xB
#define PON_POFF_REASON1		0xC
#define PON_POFF_REASON2		0xD
#define PON_SOFT_RESET_REASON1		0xE
#define PON_SOFT_RESET_REASON2		0xF
#define PON_PMIC_WD_RESET_S1_TIMER	0x54
#define PON_PMIC_WD_RESET_S2_TIMER	0x55
static irqreturn_t qpnp_pmic_wd_bark_irq(int irq, void *_pon)
{
	struct qpnp_pon *pon = _pon;

	print_pon_reg(pon, PON_PBL_STATUS);
	print_pon_reg(pon, PON_PBL_STATUS);
	print_pon_reg(pon, PON_PON_REASON1);
	print_pon_reg(pon, PON_PON_REASON2);
	print_pon_reg(pon, PON_WARM_RESET_REASON1);
	print_pon_reg(pon, PON_WARM_RESET_REASON2);
	print_pon_reg(pon, PON_POFF_REASON1);
	print_pon_reg(pon, PON_POFF_REASON2);
	print_pon_reg(pon, PON_SOFT_RESET_REASON1);
	print_pon_reg(pon, PON_SOFT_RESET_REASON2);
	print_pon_reg(pon, PON_PMIC_WD_RESET_S1_TIMER);
	print_pon_reg(pon, PON_PMIC_WD_RESET_S2_TIMER);
	panic("PMIC Watch dog triggered");

	return IRQ_HANDLED;
}

static void bark_work_func(struct work_struct *work)
{
	int rc;
@@ -811,7 +859,7 @@ qpnp_pon_config_input(struct qpnp_pon *pon, struct qpnp_pon_config *cfg)

static int qpnp_pon_config_init(struct qpnp_pon *pon)
{
	int rc = 0, i = 0;
	int rc = 0, i = 0, pmic_wd_bark_irq;
	struct device_node *pp = NULL;
	struct qpnp_pon_config *cfg;
	u8 pon_ver;
@@ -1026,6 +1074,21 @@ static int qpnp_pon_config_init(struct qpnp_pon *pon)
		}
	}

	pmic_wd_bark_irq = spmi_get_irq_byname(pon->spmi, NULL, "pmic-wd-bark");
	/* request the pmic-wd-bark irq only if it is defined */
	if (pmic_wd_bark_irq >= 0) {
		rc = devm_request_irq(&pon->spmi->dev, pmic_wd_bark_irq,
					qpnp_pmic_wd_bark_irq,
					IRQF_TRIGGER_RISING,
					"qpnp_pmic_wd_bark", pon);
		if (rc < 0) {
			dev_err(&pon->spmi->dev,
				"Can't request %d IRQ\n",
					pmic_wd_bark_irq);
			goto free_input_dev;
		}
	}

	/* register the input device */
	if (pon->pon_input) {
		rc = input_register_device(pon->pon_input);