Commit 3669e930 authored by Johannes Berg's avatar Johannes Berg Committed by Paul Mackerras
Browse files

[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: default avatarJohannes Berg <johannes@sipsolutions.net>
Acked-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
parent 71bf08b6
Loading
Loading
Loading
Loading
+95 −1
Original line number Diff line number Diff line
@@ -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,
@@ -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);
+15 −0
Original line number Diff line number Diff line
@@ -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
};

/*