[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:
Johannes Berg 2007-05-02 16:33:41 +10:00 committed by Paul Mackerras
parent 71bf08b6c0
commit 3669e93048
2 changed files with 110 additions and 1 deletions

View file

@ -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);

View file

@ -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
};
/*