mirror of
https://github.com/fail0verflow/switch-linux.git
synced 2025-05-04 02:34:21 -04:00
[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;
|
tmp |= 0x22;
|
||||||
writel(tmp, fixup->base + 4);
|
writel(tmp, fixup->base + 4);
|
||||||
spin_unlock_irqrestore(&mpic->fixup_lock, flags);
|
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,
|
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;
|
tmp |= 1;
|
||||||
writel(tmp, fixup->base + 4);
|
writel(tmp, fixup->base + 4);
|
||||||
spin_unlock_irqrestore(&mpic->fixup_lock, flags);
|
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,
|
static void __init mpic_scan_ht_pic(struct mpic *mpic, u8 __iomem *devbase,
|
||||||
|
@ -1167,6 +1179,12 @@ void __init mpic_init(struct mpic *mpic)
|
||||||
|
|
||||||
/* Set current processor priority to 0 */
|
/* Set current processor priority to 0 */
|
||||||
mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 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)
|
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();
|
mpic_setup_this_cpu();
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_SMP */
|
#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__
|
#ifdef __KERNEL__
|
||||||
|
|
||||||
#include <linux/irq.h>
|
#include <linux/irq.h>
|
||||||
|
#include <linux/sysdev.h>
|
||||||
#include <asm/dcr.h>
|
#include <asm/dcr.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -228,6 +229,14 @@ struct mpic_reg_bank {
|
||||||
#endif /* CONFIG_PPC_DCR */
|
#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 */
|
/* The instance data of a given MPIC */
|
||||||
struct mpic
|
struct mpic
|
||||||
{
|
{
|
||||||
|
@ -294,6 +303,12 @@ struct mpic
|
||||||
|
|
||||||
/* link */
|
/* link */
|
||||||
struct mpic *next;
|
struct mpic *next;
|
||||||
|
|
||||||
|
struct sys_device sysdev;
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM
|
||||||
|
struct mpic_irq_save *save_data;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Add table
Reference in a new issue