[POWERPC] MPIC sys_device & suspend/resume
This adds mpic to the system devices and implements suspend and resume for them. This is necessary to get interrupts for modules back to where they were before a suspend to disk. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
This commit is contained in:
parent
71bf08b6c0
commit
3669e93048
2 changed files with 110 additions and 1 deletions
|
@ -354,6 +354,12 @@ static void mpic_startup_ht_interrupt(struct mpic *mpic, unsigned int source,
|
|||
tmp |= 0x22;
|
||||
writel(tmp, fixup->base + 4);
|
||||
spin_unlock_irqrestore(&mpic->fixup_lock, flags);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
/* use the lowest bit inverted to the actual HW,
|
||||
* set if this fixup was enabled, clear otherwise */
|
||||
mpic->save_data[source].fixup_data = tmp | 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void mpic_shutdown_ht_interrupt(struct mpic *mpic, unsigned int source,
|
||||
|
@ -375,6 +381,12 @@ static void mpic_shutdown_ht_interrupt(struct mpic *mpic, unsigned int source,
|
|||
tmp |= 1;
|
||||
writel(tmp, fixup->base + 4);
|
||||
spin_unlock_irqrestore(&mpic->fixup_lock, flags);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
/* use the lowest bit inverted to the actual HW,
|
||||
* set if this fixup was enabled, clear otherwise */
|
||||
mpic->save_data[source].fixup_data = tmp & ~1;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void __init mpic_scan_ht_pic(struct mpic *mpic, u8 __iomem *devbase,
|
||||
|
@ -1143,7 +1155,7 @@ void __init mpic_init(struct mpic *mpic)
|
|||
/* Do the HT PIC fixups on U3 broken mpic */
|
||||
DBG("MPIC flags: %x\n", mpic->flags);
|
||||
if ((mpic->flags & MPIC_U3_HT_IRQS) && (mpic->flags & MPIC_PRIMARY))
|
||||
mpic_scan_ht_pics(mpic);
|
||||
mpic_scan_ht_pics(mpic);
|
||||
|
||||
for (i = 0; i < mpic->num_sources; i++) {
|
||||
/* start with vector = source number, and masked */
|
||||
|
@ -1167,6 +1179,12 @@ void __init mpic_init(struct mpic *mpic)
|
|||
|
||||
/* Set current processor priority to 0 */
|
||||
mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
/* allocate memory to save mpic state */
|
||||
mpic->save_data = alloc_bootmem(mpic->num_sources * sizeof(struct mpic_irq_save));
|
||||
BUG_ON(mpic->save_data == NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
void __init mpic_set_clk_ratio(struct mpic *mpic, u32 clock_ratio)
|
||||
|
@ -1420,3 +1438,79 @@ void __devinit smp_mpic_setup_cpu(int cpu)
|
|||
mpic_setup_this_cpu();
|
||||
}
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int mpic_suspend(struct sys_device *dev, pm_message_t state)
|
||||
{
|
||||
struct mpic *mpic = container_of(dev, struct mpic, sysdev);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < mpic->num_sources; i++) {
|
||||
mpic->save_data[i].vecprio =
|
||||
mpic_irq_read(i, MPIC_INFO(IRQ_VECTOR_PRI));
|
||||
mpic->save_data[i].dest =
|
||||
mpic_irq_read(i, MPIC_INFO(IRQ_DESTINATION));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mpic_resume(struct sys_device *dev)
|
||||
{
|
||||
struct mpic *mpic = container_of(dev, struct mpic, sysdev);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < mpic->num_sources; i++) {
|
||||
mpic_irq_write(i, MPIC_INFO(IRQ_VECTOR_PRI),
|
||||
mpic->save_data[i].vecprio);
|
||||
mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION),
|
||||
mpic->save_data[i].dest);
|
||||
|
||||
#ifdef CONFIG_MPIC_U3_HT_IRQS
|
||||
{
|
||||
struct mpic_irq_fixup *fixup = &mpic->fixups[i];
|
||||
|
||||
if (fixup->base) {
|
||||
/* we use the lowest bit in an inverted meaning */
|
||||
if ((mpic->save_data[i].fixup_data & 1) == 0)
|
||||
continue;
|
||||
|
||||
/* Enable and configure */
|
||||
writeb(0x10 + 2 * fixup->index, fixup->base + 2);
|
||||
|
||||
writel(mpic->save_data[i].fixup_data & ~1,
|
||||
fixup->base + 4);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} /* end for loop */
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct sysdev_class mpic_sysclass = {
|
||||
#ifdef CONFIG_PM
|
||||
.resume = mpic_resume,
|
||||
.suspend = mpic_suspend,
|
||||
#endif
|
||||
set_kset_name("mpic"),
|
||||
};
|
||||
|
||||
static int mpic_init_sys(void)
|
||||
{
|
||||
struct mpic *mpic = mpics;
|
||||
int error, id = 0;
|
||||
|
||||
error = sysdev_class_register(&mpic_sysclass);
|
||||
|
||||
while (mpic && !error) {
|
||||
mpic->sysdev.cls = &mpic_sysclass;
|
||||
mpic->sysdev.id = id++;
|
||||
error = sysdev_register(&mpic->sysdev);
|
||||
mpic = mpic->next;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
device_initcall(mpic_init_sys);
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#ifdef __KERNEL__
|
||||
|
||||
#include <linux/irq.h>
|
||||
#include <linux/sysdev.h>
|
||||
#include <asm/dcr.h>
|
||||
|
||||
/*
|
||||
|
@ -228,6 +229,14 @@ struct mpic_reg_bank {
|
|||
#endif /* CONFIG_PPC_DCR */
|
||||
};
|
||||
|
||||
struct mpic_irq_save {
|
||||
u32 vecprio,
|
||||
dest;
|
||||
#ifdef CONFIG_MPIC_U3_HT_IRQS
|
||||
u32 fixup_data;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* The instance data of a given MPIC */
|
||||
struct mpic
|
||||
{
|
||||
|
@ -294,6 +303,12 @@ struct mpic
|
|||
|
||||
/* link */
|
||||
struct mpic *next;
|
||||
|
||||
struct sys_device sysdev;
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
struct mpic_irq_save *save_data;
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in a new issue