Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.14 257 lines 6.3 kB view raw
1/* 2 * arch/ppc/syslib/mpc52xx_pic.c 3 * 4 * Programmable Interrupt Controller functions for the Freescale MPC52xx 5 * embedded CPU. 6 * 7 * 8 * Maintainer : Sylvain Munaut <tnt@246tNt.com> 9 * 10 * Based on (well, mostly copied from) the code from the 2.4 kernel by 11 * Dale Farnsworth <dfarnsworth@mvista.com> and Kent Borg. 12 * 13 * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com> 14 * Copyright (C) 2003 Montavista Software, Inc 15 * 16 * This file is licensed under the terms of the GNU General Public License 17 * version 2. This program is licensed "as is" without any warranty of any 18 * kind, whether express or implied. 19 */ 20 21#include <linux/stddef.h> 22#include <linux/init.h> 23#include <linux/sched.h> 24#include <linux/signal.h> 25#include <linux/stddef.h> 26#include <linux/delay.h> 27#include <linux/irq.h> 28 29#include <asm/io.h> 30#include <asm/processor.h> 31#include <asm/system.h> 32#include <asm/irq.h> 33#include <asm/mpc52xx.h> 34 35 36static struct mpc52xx_intr __iomem *intr; 37static struct mpc52xx_sdma __iomem *sdma; 38 39static void 40mpc52xx_ic_disable(unsigned int irq) 41{ 42 u32 val; 43 44 if (irq == MPC52xx_IRQ0) { 45 val = in_be32(&intr->ctrl); 46 val &= ~(1 << 11); 47 out_be32(&intr->ctrl, val); 48 } 49 else if (irq < MPC52xx_IRQ1) { 50 BUG(); 51 } 52 else if (irq <= MPC52xx_IRQ3) { 53 val = in_be32(&intr->ctrl); 54 val &= ~(1 << (10 - (irq - MPC52xx_IRQ1))); 55 out_be32(&intr->ctrl, val); 56 } 57 else if (irq < MPC52xx_SDMA_IRQ_BASE) { 58 val = in_be32(&intr->main_mask); 59 val |= 1 << (16 - (irq - MPC52xx_MAIN_IRQ_BASE)); 60 out_be32(&intr->main_mask, val); 61 } 62 else if (irq < MPC52xx_PERP_IRQ_BASE) { 63 val = in_be32(&sdma->IntMask); 64 val |= 1 << (irq - MPC52xx_SDMA_IRQ_BASE); 65 out_be32(&sdma->IntMask, val); 66 } 67 else { 68 val = in_be32(&intr->per_mask); 69 val |= 1 << (31 - (irq - MPC52xx_PERP_IRQ_BASE)); 70 out_be32(&intr->per_mask, val); 71 } 72} 73 74static void 75mpc52xx_ic_enable(unsigned int irq) 76{ 77 u32 val; 78 79 if (irq == MPC52xx_IRQ0) { 80 val = in_be32(&intr->ctrl); 81 val |= 1 << 11; 82 out_be32(&intr->ctrl, val); 83 } 84 else if (irq < MPC52xx_IRQ1) { 85 BUG(); 86 } 87 else if (irq <= MPC52xx_IRQ3) { 88 val = in_be32(&intr->ctrl); 89 val |= 1 << (10 - (irq - MPC52xx_IRQ1)); 90 out_be32(&intr->ctrl, val); 91 } 92 else if (irq < MPC52xx_SDMA_IRQ_BASE) { 93 val = in_be32(&intr->main_mask); 94 val &= ~(1 << (16 - (irq - MPC52xx_MAIN_IRQ_BASE))); 95 out_be32(&intr->main_mask, val); 96 } 97 else if (irq < MPC52xx_PERP_IRQ_BASE) { 98 val = in_be32(&sdma->IntMask); 99 val &= ~(1 << (irq - MPC52xx_SDMA_IRQ_BASE)); 100 out_be32(&sdma->IntMask, val); 101 } 102 else { 103 val = in_be32(&intr->per_mask); 104 val &= ~(1 << (31 - (irq - MPC52xx_PERP_IRQ_BASE))); 105 out_be32(&intr->per_mask, val); 106 } 107} 108 109static void 110mpc52xx_ic_ack(unsigned int irq) 111{ 112 u32 val; 113 114 /* 115 * Only some irqs are reset here, others in interrupting hardware. 116 */ 117 118 switch (irq) { 119 case MPC52xx_IRQ0: 120 val = in_be32(&intr->ctrl); 121 val |= 0x08000000; 122 out_be32(&intr->ctrl, val); 123 break; 124 case MPC52xx_CCS_IRQ: 125 val = in_be32(&intr->enc_status); 126 val |= 0x00000400; 127 out_be32(&intr->enc_status, val); 128 break; 129 case MPC52xx_IRQ1: 130 val = in_be32(&intr->ctrl); 131 val |= 0x04000000; 132 out_be32(&intr->ctrl, val); 133 break; 134 case MPC52xx_IRQ2: 135 val = in_be32(&intr->ctrl); 136 val |= 0x02000000; 137 out_be32(&intr->ctrl, val); 138 break; 139 case MPC52xx_IRQ3: 140 val = in_be32(&intr->ctrl); 141 val |= 0x01000000; 142 out_be32(&intr->ctrl, val); 143 break; 144 default: 145 if (irq >= MPC52xx_SDMA_IRQ_BASE 146 && irq < (MPC52xx_SDMA_IRQ_BASE + MPC52xx_SDMA_IRQ_NUM)) { 147 out_be32(&sdma->IntPend, 148 1 << (irq - MPC52xx_SDMA_IRQ_BASE)); 149 } 150 break; 151 } 152} 153 154static void 155mpc52xx_ic_disable_and_ack(unsigned int irq) 156{ 157 mpc52xx_ic_disable(irq); 158 mpc52xx_ic_ack(irq); 159} 160 161static void 162mpc52xx_ic_end(unsigned int irq) 163{ 164 if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) 165 mpc52xx_ic_enable(irq); 166} 167 168static struct hw_interrupt_type mpc52xx_ic = { 169 .typename = " MPC52xx ", 170 .enable = mpc52xx_ic_enable, 171 .disable = mpc52xx_ic_disable, 172 .ack = mpc52xx_ic_disable_and_ack, 173 .end = mpc52xx_ic_end, 174}; 175 176void __init 177mpc52xx_init_irq(void) 178{ 179 int i; 180 u32 intr_ctrl; 181 182 /* Remap the necessary zones */ 183 intr = ioremap(MPC52xx_PA(MPC52xx_INTR_OFFSET), MPC52xx_INTR_SIZE); 184 sdma = ioremap(MPC52xx_PA(MPC52xx_SDMA_OFFSET), MPC52xx_SDMA_SIZE); 185 186 if ((intr==NULL) || (sdma==NULL)) 187 panic("Can't ioremap PIC/SDMA register for init_irq !"); 188 189 /* Disable all interrupt sources. */ 190 out_be32(&sdma->IntPend, 0xffffffff); /* 1 means clear pending */ 191 out_be32(&sdma->IntMask, 0xffffffff); /* 1 means disabled */ 192 out_be32(&intr->per_mask, 0x7ffffc00); /* 1 means disabled */ 193 out_be32(&intr->main_mask, 0x00010fff); /* 1 means disabled */ 194 intr_ctrl = in_be32(&intr->ctrl); 195 intr_ctrl &= 0x00ff0000; /* Keeps IRQ[0-3] config */ 196 intr_ctrl |= 0x0f000000 | /* clear IRQ 0-3 */ 197 0x00001000 | /* MEE master external enable */ 198 0x00000000 | /* 0 means disable IRQ 0-3 */ 199 0x00000001; /* CEb route critical normally */ 200 out_be32(&intr->ctrl, intr_ctrl); 201 202 /* Zero a bunch of the priority settings. */ 203 out_be32(&intr->per_pri1, 0); 204 out_be32(&intr->per_pri2, 0); 205 out_be32(&intr->per_pri3, 0); 206 out_be32(&intr->main_pri1, 0); 207 out_be32(&intr->main_pri2, 0); 208 209 /* Initialize irq_desc[i].handler's with mpc52xx_ic. */ 210 for (i = 0; i < NR_IRQS; i++) { 211 irq_desc[i].handler = &mpc52xx_ic; 212 irq_desc[i].status = IRQ_LEVEL; 213 } 214 215 #define IRQn_MODE(intr_ctrl,irq) (((intr_ctrl) >> (22-(i<<1))) & 0x03) 216 for (i=0 ; i<4 ; i++) { 217 int mode; 218 mode = IRQn_MODE(intr_ctrl,i); 219 if ((mode == 0x1) || (mode == 0x2)) 220 irq_desc[i?MPC52xx_IRQ1+i-1:MPC52xx_IRQ0].status = 0; 221 } 222} 223 224int 225mpc52xx_get_irq(struct pt_regs *regs) 226{ 227 u32 status; 228 int irq = -1; 229 230 status = in_be32(&intr->enc_status); 231 232 if (status & 0x00000400) { /* critical */ 233 irq = (status >> 8) & 0x3; 234 if (irq == 2) /* high priority peripheral */ 235 goto peripheral; 236 irq += MPC52xx_CRIT_IRQ_BASE; 237 } 238 else if (status & 0x00200000) { /* main */ 239 irq = (status >> 16) & 0x1f; 240 if (irq == 4) /* low priority peripheral */ 241 goto peripheral; 242 irq += MPC52xx_MAIN_IRQ_BASE; 243 } 244 else if (status & 0x20000000) { /* peripheral */ 245peripheral: 246 irq = (status >> 24) & 0x1f; 247 if (irq == 0) { /* bestcomm */ 248 status = in_be32(&sdma->IntPend); 249 irq = ffs(status) + MPC52xx_SDMA_IRQ_BASE-1; 250 } 251 else 252 irq += MPC52xx_PERP_IRQ_BASE; 253 } 254 255 return irq; 256} 257