Skip to content

Commit

Permalink
[POWERPC] MPIC sys_device & suspend/resume
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Johannes Berg authored and Paul Mackerras committed May 7, 2007
1 parent 71bf08b commit 3669e93
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 1 deletion.
96 changes: 95 additions & 1 deletion arch/powerpc/sysdev/mpic.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -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 */
Expand All @@ -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)
Expand Down Expand Up @@ -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);
15 changes: 15 additions & 0 deletions include/asm-powerpc/mpic.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#ifdef __KERNEL__

#include <linux/irq.h>
#include <linux/sysdev.h>
#include <asm/dcr.h>

/*
Expand Down Expand Up @@ -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
{
Expand Down Expand Up @@ -294,6 +303,12 @@ struct mpic

/* link */
struct mpic *next;

struct sys_device sysdev;

#ifdef CONFIG_PM
struct mpic_irq_save *save_data;
#endif
};

/*
Expand Down

0 comments on commit 3669e93

Please sign in to comment.