1/* 2 * 3 * Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu> 4 * 5 * Module name: ppc403_pic.c 6 * 7 * Description: 8 * Interrupt controller driver for PowerPC 403-based processors. 9 */ 10 11/* 12 * The PowerPC 403 cores' Asynchronous Interrupt Controller (AIC) has 13 * 32 possible interrupts, a majority of which are not implemented on 14 * all cores. There are six configurable, external interrupt pins and 15 * there are eight internal interrupts for the on-chip serial port 16 * (SPU), DMA controller, and JTAG controller. 17 * 18 */ 19 20#include <linux/init.h> 21#include <linux/sched.h> 22#include <linux/signal.h> 23#include <linux/stddef.h> 24 25#include <asm/processor.h> 26#include <asm/system.h> 27#include <asm/irq.h> 28#include <asm/ppc4xx_pic.h> 29#include <asm/machdep.h> 30 31/* Function Prototypes */ 32 33static void ppc403_aic_enable(unsigned int irq); 34static void ppc403_aic_disable(unsigned int irq); 35static void ppc403_aic_disable_and_ack(unsigned int irq); 36 37static struct hw_interrupt_type ppc403_aic = { 38 .typename = "403GC AIC", 39 .enable = ppc403_aic_enable, 40 .disable = ppc403_aic_disable, 41 .ack = ppc403_aic_disable_and_ack, 42}; 43 44int 45ppc403_pic_get_irq(void) 46{ 47 int irq; 48 unsigned long bits; 49 50 /* 51 * Only report the status of those interrupts that are actually 52 * enabled. 53 */ 54 55 bits = mfdcr(DCRN_EXISR) & mfdcr(DCRN_EXIER); 56 57 /* 58 * Walk through the interrupts from highest priority to lowest, and 59 * report the first pending interrupt found. 60 * We want PPC, not C bit numbering, so just subtract the ffs() 61 * result from 32. 62 */ 63 irq = 32 - ffs(bits); 64 65 if (irq == NR_AIC_IRQS) 66 irq = -1; 67 68 return (irq); 69} 70 71static void 72ppc403_aic_enable(unsigned int irq) 73{ 74 int bit, word; 75 76 bit = irq & 0x1f; 77 word = irq >> 5; 78 79 ppc_cached_irq_mask[word] |= (1 << (31 - bit)); 80 mtdcr(DCRN_EXIER, ppc_cached_irq_mask[word]); 81} 82 83static void 84ppc403_aic_disable(unsigned int irq) 85{ 86 int bit, word; 87 88 bit = irq & 0x1f; 89 word = irq >> 5; 90 91 ppc_cached_irq_mask[word] &= ~(1 << (31 - bit)); 92 mtdcr(DCRN_EXIER, ppc_cached_irq_mask[word]); 93} 94 95static void 96ppc403_aic_disable_and_ack(unsigned int irq) 97{ 98 int bit, word; 99 100 bit = irq & 0x1f; 101 word = irq >> 5; 102 103 ppc_cached_irq_mask[word] &= ~(1 << (31 - bit)); 104 mtdcr(DCRN_EXIER, ppc_cached_irq_mask[word]); 105 mtdcr(DCRN_EXISR, (1 << (31 - bit))); 106} 107 108void __init 109ppc4xx_pic_init(void) 110{ 111 int i; 112 113 /* 114 * Disable all external interrupts until they are 115 * explicitly requested. 116 */ 117 ppc_cached_irq_mask[0] = 0; 118 119 mtdcr(DCRN_EXIER, ppc_cached_irq_mask[0]); 120 121 ppc_md.get_irq = ppc403_pic_get_irq; 122 123 for (i = 0; i < NR_IRQS; i++) 124 irq_desc[i].chip = &ppc403_aic; 125} 126