ppc403_pic.c 2.5 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
/*
 *
 *    Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
 *
 *    Module name: ppc403_pic.c
 *
 *    Description:
 *      Interrupt controller driver for PowerPC 403-based processors.
 */

/*
 * The PowerPC 403 cores' Asynchronous Interrupt Controller (AIC) has
 * 32 possible interrupts, a majority of which are not implemented on
 * all cores. There are six configurable, external interrupt pins and
 * there are eight internal interrupts for the on-chip serial port
 * (SPU), DMA controller, and JTAG controller.
 *
 */

#include <linux/init.h>
#include <linux/sched.h>
#include <linux/signal.h>
#include <linux/stddef.h>

#include <asm/processor.h>
#include <asm/system.h>
#include <asm/irq.h>
#include <asm/ppc4xx_pic.h>
P
Paul Mackerras 已提交
29
#include <asm/machdep.h>
L
Linus Torvalds 已提交
30 31 32 33 34 35 36 37

/* Function Prototypes */

static void ppc403_aic_enable(unsigned int irq);
static void ppc403_aic_disable(unsigned int irq);
static void ppc403_aic_disable_and_ack(unsigned int irq);

static struct hw_interrupt_type ppc403_aic = {
38 39 40 41
	.typename = "403GC AIC",
	.enable = ppc403_aic_enable,
	.disable = ppc403_aic_disable,
	.ack = ppc403_aic_disable_and_ack,
L
Linus Torvalds 已提交
42 43 44
};

int
A
Al Viro 已提交
45
ppc403_pic_get_irq(void)
L
Linus Torvalds 已提交
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
{
	int irq;
	unsigned long bits;

	/*
	 * Only report the status of those interrupts that are actually
	 * enabled.
	 */

	bits = mfdcr(DCRN_EXISR) & mfdcr(DCRN_EXIER);

	/*
	 * Walk through the interrupts from highest priority to lowest, and
	 * report the first pending interrupt found.
	 * We want PPC, not C bit numbering, so just subtract the ffs()
	 * result from 32.
	 */
	irq = 32 - ffs(bits);

	if (irq == NR_AIC_IRQS)
		irq = -1;

	return (irq);
}

static void
ppc403_aic_enable(unsigned int irq)
{
	int bit, word;

	bit = irq & 0x1f;
	word = irq >> 5;

	ppc_cached_irq_mask[word] |= (1 << (31 - bit));
	mtdcr(DCRN_EXIER, ppc_cached_irq_mask[word]);
}

static void
ppc403_aic_disable(unsigned int irq)
{
	int bit, word;

	bit = irq & 0x1f;
	word = irq >> 5;

	ppc_cached_irq_mask[word] &= ~(1 << (31 - bit));
	mtdcr(DCRN_EXIER, ppc_cached_irq_mask[word]);
}

static void
ppc403_aic_disable_and_ack(unsigned int irq)
{
	int bit, word;

	bit = irq & 0x1f;
	word = irq >> 5;

	ppc_cached_irq_mask[word] &= ~(1 << (31 - bit));
	mtdcr(DCRN_EXIER, ppc_cached_irq_mask[word]);
	mtdcr(DCRN_EXISR, (1 << (31 - bit)));
}

void __init
ppc4xx_pic_init(void)
{
	int i;

	/*
	 * Disable all external interrupts until they are
	 * explicity requested.
	 */
	ppc_cached_irq_mask[0] = 0;

	mtdcr(DCRN_EXIER, ppc_cached_irq_mask[0]);

	ppc_md.get_irq = ppc403_pic_get_irq;

	for (i = 0; i < NR_IRQS; i++)
124
		irq_desc[i].chip = &ppc403_aic;
L
Linus Torvalds 已提交
125
}