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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 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 124 125
|
/*
*
* 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>
#include <asm/machdep.h>
/* 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 = {
.typename = "403GC AIC",
.enable = ppc403_aic_enable,
.disable = ppc403_aic_disable,
.ack = ppc403_aic_disable_and_ack,
};
int
ppc403_pic_get_irq(struct pt_regs *regs)
{
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++)
irq_desc[i].chip = &ppc403_aic;
}
|