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

Commit 69dc3fcd authored by Abhijeet Dharmapurikar's avatar Abhijeet Dharmapurikar Committed by David Collins
Browse files

spmi: pmic-arb: support show_resume_irq



show_resume_irq is used to debug interrupts that cause wakeup.
Support it for spmi arbiter's interrupt controller.

Change-Id: I52d51c09d7ff316248542c84a1cd65a28e2283da
Signed-off-by: default avatarAbhijeet Dharmapurikar <adharmap@codeaurora.org>
parent 57132f55
Loading
Loading
Loading
Loading
+43 −8
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/spmi.h>
#include <linux/syscore_ops.h>

/* PMIC Arbiter configuration registers */
#define PMIC_ARB_VERSION		0x0000
@@ -159,6 +160,7 @@ struct spmi_pmic_arb {
	u16			last_apid;
	struct apid_data	apid_data[PMIC_ARB_MAX_PERIPHS];
};
static struct spmi_pmic_arb *the_pa;

/**
 * pmic_arb_ver: version dependent functionality.
@@ -525,7 +527,7 @@ static void cleanup_irq(struct spmi_pmic_arb *pa, u16 apid, int id)
				irq_mask, ppid);
}

static void periph_interrupt(struct spmi_pmic_arb *pa, u16 apid)
static void periph_interrupt(struct spmi_pmic_arb *pa, u16 apid, bool show)
{
	unsigned int irq;
	u32 status;
@@ -542,22 +544,32 @@ static void periph_interrupt(struct spmi_pmic_arb *pa, u16 apid)
			cleanup_irq(pa, apid, id);
			continue;
		}
		if (show) {
			struct irq_desc *desc;
			const char *name = "null";

			desc = irq_to_desc(irq);
			if (desc == NULL)
				name = "stray irq";
			else if (desc->action && desc->action->name)
				name = desc->action->name;

			pr_warn("spmi_show_resume_irq: %d triggered [0x%01x, 0x%02x, 0x%01x] %s\n",
				irq, sid, per, id, name);
		} else {
			generic_handle_irq(irq);
		}
	}
}

static void pmic_arb_chained_irq(struct irq_desc *desc)
static void __pmic_arb_chained_irq(struct spmi_pmic_arb *pa, bool show)
{
	struct spmi_pmic_arb *pa = irq_desc_get_handler_data(desc);
	struct irq_chip *chip = irq_desc_get_chip(desc);
	void __iomem *intr = pa->intr;
	int first = pa->min_apid >> 5;
	int last = pa->max_apid >> 5;
	u32 status, enable;
	int i, id, apid;

	chained_irq_enter(chip, desc);

	for (i = first; i <= last; ++i) {
		status = readl_relaxed(intr +
				      pa->ver_ops->owner_acc_status(pa->ee, i));
@@ -568,10 +580,18 @@ static void pmic_arb_chained_irq(struct irq_desc *desc)
			enable = readl_relaxed(intr +
					pa->ver_ops->acc_enable(apid));
			if (enable & SPMI_PIC_ACC_ENABLE_BIT)
				periph_interrupt(pa, apid);
				periph_interrupt(pa, apid, show);
		}
	}
}

static void pmic_arb_chained_irq(struct irq_desc *desc)
{
	struct spmi_pmic_arb *pa = irq_desc_get_handler_data(desc);
	struct irq_chip *chip = irq_desc_get_chip(desc);

	chained_irq_enter(chip, desc);
	__pmic_arb_chained_irq(pa, false);
	chained_irq_exit(chip, desc);
}

@@ -988,6 +1008,16 @@ static const struct irq_domain_ops pmic_arb_irq_domain_ops = {
	.xlate	= qpnpint_irq_domain_dt_translate,
};

static void spmi_pmic_arb_resume(void)
{
	if (spmi_show_resume_irq())
		__pmic_arb_chained_irq(the_pa, true);
}

static struct syscore_ops spmi_pmic_arb_syscore_ops = {
	.resume = spmi_pmic_arb_resume,
};

static int spmi_pmic_arb_probe(struct platform_device *pdev)
{
	struct spmi_pmic_arb *pa;
@@ -1154,6 +1184,8 @@ static int spmi_pmic_arb_probe(struct platform_device *pdev)
	if (err)
		goto err_domain_remove;

	the_pa = pa;
	register_syscore_ops(&spmi_pmic_arb_syscore_ops);
	return 0;

err_domain_remove:
@@ -1168,8 +1200,11 @@ static int spmi_pmic_arb_remove(struct platform_device *pdev)
{
	struct spmi_controller *ctrl = platform_get_drvdata(pdev);
	struct spmi_pmic_arb *pa = spmi_controller_get_drvdata(ctrl);

	spmi_controller_remove(ctrl);
	irq_set_chained_handler_and_data(pa->irq, NULL, NULL);
	unregister_syscore_ops(&spmi_pmic_arb_syscore_ops);
	the_pa = NULL;
	irq_domain_remove(pa->domain);
	spmi_controller_put(ctrl);
	return 0;
+14 −1
Original line number Diff line number Diff line
/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -171,6 +171,19 @@ static inline void spmi_driver_unregister(struct spmi_driver *sdrv)
	module_driver(__spmi_driver, spmi_driver_register, \
			spmi_driver_unregister)

#ifdef CONFIG_QCOM_SHOW_RESUME_IRQ
extern int msm_show_resume_irq_mask;
static inline bool spmi_show_resume_irq(void)
{
	return msm_show_resume_irq_mask;
}
#else
static inline bool spmi_show_resume_irq(void)
{
	return false;
}
#endif

int spmi_register_read(struct spmi_device *sdev, u8 addr, u8 *buf);
int spmi_ext_register_read(struct spmi_device *sdev, u8 addr, u8 *buf,
			   size_t len);