Skip to content

Commit 2dcec7a

Browse files
Magnus Dammpmundt
authored andcommitted
sh: intc: set_irq_wake() support
Add set_irq_wake() support to intc using sysdev and suspend. The intc controllers are put on a list at registration time and registered as sysdev devices later on during the boot. The sysdev class suspend callback is used to find irqs with wakeup enabled belonging to our intc controller. Such irqs are simply enabled so wakeup interrupts may reach the cpu. Signed-off-by: Magnus Damm <damm@igel.co.jp> Signed-off-by: Paul Mundt <lethal@linux-sh.org>
1 parent f7dd254 commit 2dcec7a

File tree

1 file changed

+65
-0
lines changed

1 file changed

+65
-0
lines changed

drivers/sh/intc.c

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
#include <linux/interrupt.h>
2323
#include <linux/bootmem.h>
2424
#include <linux/sh_intc.h>
25+
#include <linux/sysdev.h>
26+
#include <linux/list.h>
2527

2628
#define _INTC_MK(fn, mode, addr_e, addr_d, width, shift) \
2729
((shift) | ((width) << 5) | ((fn) << 9) | ((mode) << 13) | \
@@ -40,6 +42,8 @@ struct intc_handle_int {
4042
};
4143

4244
struct intc_desc_int {
45+
struct list_head list;
46+
struct sys_device sysdev;
4347
unsigned long *reg;
4448
#ifdef CONFIG_SMP
4549
unsigned long *smp;
@@ -52,6 +56,8 @@ struct intc_desc_int {
5256
struct irq_chip chip;
5357
};
5458

59+
static LIST_HEAD(intc_list);
60+
5561
#ifdef CONFIG_SMP
5662
#define IS_SMP(x) x.smp
5763
#define INTC_REG(d, x, c) (d->reg[(x)] + ((d->smp[(x)] & 0xff) * c))
@@ -232,6 +238,11 @@ static void intc_disable(unsigned int irq)
232238
}
233239
}
234240

241+
static int intc_set_wake(unsigned int irq, unsigned int on)
242+
{
243+
return 0; /* allow wakeup, but setup hardware in intc_suspend() */
244+
}
245+
235246
#if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4A)
236247
static void intc_mask_ack(unsigned int irq)
237248
{
@@ -664,6 +675,9 @@ void __init register_intc_controller(struct intc_desc *desc)
664675

665676
d = alloc_bootmem(sizeof(*d));
666677

678+
INIT_LIST_HEAD(&d->list);
679+
list_add(&d->list, &intc_list);
680+
667681
d->nr_reg = desc->mask_regs ? desc->nr_mask_regs * 2 : 0;
668682
d->nr_reg += desc->prio_regs ? desc->nr_prio_regs * 2 : 0;
669683
d->nr_reg += desc->sense_regs ? desc->nr_sense_regs : 0;
@@ -711,6 +725,7 @@ void __init register_intc_controller(struct intc_desc *desc)
711725
d->chip.disable = intc_disable;
712726
d->chip.shutdown = intc_disable;
713727
d->chip.set_type = intc_set_sense;
728+
d->chip.set_wake = intc_set_wake;
714729

715730
#if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4A)
716731
if (desc->ack_regs) {
@@ -761,3 +776,53 @@ void __init register_intc_controller(struct intc_desc *desc)
761776
intc_register_irq(desc, d, vect->enum_id, evt2irq(vect->vect));
762777
}
763778
}
779+
780+
static int intc_suspend(struct sys_device *dev, pm_message_t state)
781+
{
782+
struct intc_desc_int *d;
783+
struct irq_desc *desc;
784+
int irq;
785+
786+
/* get intc controller associated with this sysdev */
787+
d = container_of(dev, struct intc_desc_int, sysdev);
788+
789+
/* enable wakeup irqs belonging to this intc controller */
790+
for_each_irq_desc(irq, desc) {
791+
if ((desc->status & IRQ_WAKEUP) && (desc->chip == &d->chip))
792+
intc_enable(irq);
793+
}
794+
795+
return 0;
796+
}
797+
798+
static struct sysdev_class intc_sysdev_class = {
799+
.name = "intc",
800+
.suspend = intc_suspend,
801+
};
802+
803+
/* register this intc as sysdev to allow suspend/resume */
804+
static int __init register_intc_sysdevs(void)
805+
{
806+
struct intc_desc_int *d;
807+
int error;
808+
int id = 0;
809+
810+
error = sysdev_class_register(&intc_sysdev_class);
811+
if (!error) {
812+
list_for_each_entry(d, &intc_list, list) {
813+
d->sysdev.id = id;
814+
d->sysdev.cls = &intc_sysdev_class;
815+
error = sysdev_register(&d->sysdev);
816+
if (error)
817+
break;
818+
id++;
819+
}
820+
}
821+
822+
if (error)
823+
pr_warning("intc: sysdev registration error\n");
824+
825+
return error;
826+
}
827+
828+
device_initcall(register_intc_sysdevs);

0 commit comments

Comments
 (0)