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: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
This commit is contained in:
parent
85d7e134cc
commit
9c08064350
2 changed files with 57 additions and 9 deletions
|
@ -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;
|
||||
}
|
||||
generic_handle_irq(irq);
|
||||
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;
|
||||
|
@ -1153,6 +1183,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:
|
||||
|
@ -1167,8 +1199,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;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* 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);
|
||||
|
|
Loading…
Add table
Reference in a new issue