Loading...
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 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 | /* * BK Id: SCCS/s.ppc4xx_pic.c 1.5 05/17/01 18:14:21 cort */ /* * * Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu> * * Module name: ppc4xx_pic.c * * Description: * Interrupt controller driver for PowerPC 4xx-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. * * The PowerPC 405 cores' Universal Interrupt Controller (UIC) has 32 * possible interrupts as well. There are seven, configurable external * interrupt pins and there are 17 internal interrupts for the on-chip * serial port, DMA controller, on-chip Ethernet controller, PCI, etc. * */ #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 "local_irq.h" #include "ppc4xx_pic.h" /* Global Variables */ struct hw_interrupt_type *ppc4xx_pic; /* 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 void ppc405_uic_enable(unsigned int irq); static void ppc405_uic_disable(unsigned int irq); static void ppc405_uic_disable_and_ack(unsigned int irq); static struct hw_interrupt_type ppc403_aic = { "403GC AIC", NULL, NULL, ppc403_aic_enable, ppc403_aic_disable, ppc403_aic_disable_and_ack, 0 }; static struct hw_interrupt_type ppc405_uic = { "405GP UIC", NULL, NULL, ppc405_uic_enable, ppc405_uic_disable, ppc405_uic_disable_and_ack, 0 }; /* * Document me. */ void __init ppc4xx_pic_init(void) { unsigned long ver = PVR_VER(mfspr(SPRN_PVR)); switch (ver) { case PVR_VER(PVR_403GC): /* * Disable all external interrupts until they are * explicity requested. */ ppc_cached_irq_mask[0] = 0; mtdcr(DCRN_EXIER, 0); ppc4xx_pic = &ppc403_aic; break; case PVR_VER(PVR_405GP): ppc4xx_pic = &ppc405_uic; break; } return; } /* * XXX - Currently 403-specific! * * Document me. */ int ppc4xx_pic_get_irq(struct pt_regs *regs) { int irq; unsigned long bits, mask = (1 << 31); /* * 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. */ for (irq = 0; irq < NR_IRQS; irq++, mask >>= 1) { if (bits & mask) break; } return (irq); } /* * Document me. */ 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]); } /* * Document me. */ 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]); } /* * Document me. */ 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))); } /* * Document me. */ static void ppc405_uic_enable(unsigned int irq) { /* XXX - Implement me. */ } /* * Document me. */ static void ppc405_uic_disable(unsigned int irq) { /* XXX - Implement me. */ } /* * Document me. */ static void ppc405_uic_disable_and_ack(unsigned int irq) { /* XXX - Implement me. */ } |