1/* 2 * Interrupt controller driver for PowerPC 4xx-based processors. 3 * 4 * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net> 5 * Copyright (c) 2004, 2005 Zultys Technologies 6 * 7 * Based on original code by 8 * Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu> 9 * Armin Custer <akuster@mvista.com> 10 * 11 * This program is free software; you can redistribute it and/or modify it 12 * under the terms of the GNU General Public License as published by the 13 * Free Software Foundation; either version 2 of the License, or (at your 14 * option) any later version. 15*/ 16#include <linux/init.h> 17#include <linux/sched.h> 18#include <linux/signal.h> 19#include <linux/stddef.h> 20 21#include <asm/processor.h> 22#include <asm/system.h> 23#include <asm/irq.h> 24#include <asm/ppc4xx_pic.h> 25#include <asm/machdep.h> 26 27/* See comment in include/arch-ppc/ppc4xx_pic.h 28 * for more info about these two variables 29 */ 30extern struct ppc4xx_uic_settings ppc4xx_core_uic_cfg[NR_UICS] 31 __attribute__ ((weak)); 32extern unsigned char ppc4xx_uic_ext_irq_cfg[] __attribute__ ((weak)); 33 34#define IRQ_MASK_UIC0(irq) (1 << (31 - (irq))) 35#define IRQ_MASK_UICx(irq) (1 << (31 - ((irq) & 0x1f))) 36#define IRQ_MASK_UIC1(irq) IRQ_MASK_UICx(irq) 37#define IRQ_MASK_UIC2(irq) IRQ_MASK_UICx(irq) 38#define IRQ_MASK_UIC3(irq) IRQ_MASK_UICx(irq) 39 40#define UIC_HANDLERS(n) \ 41static void ppc4xx_uic##n##_enable(unsigned int irq) \ 42{ \ 43 u32 mask = IRQ_MASK_UIC##n(irq); \ 44 if (irq_desc[irq].status & IRQ_LEVEL) \ 45 mtdcr(DCRN_UIC_SR(UIC##n), mask); \ 46 ppc_cached_irq_mask[n] |= mask; \ 47 mtdcr(DCRN_UIC_ER(UIC##n), ppc_cached_irq_mask[n]); \ 48} \ 49 \ 50static void ppc4xx_uic##n##_disable(unsigned int irq) \ 51{ \ 52 ppc_cached_irq_mask[n] &= ~IRQ_MASK_UIC##n(irq); \ 53 mtdcr(DCRN_UIC_ER(UIC##n), ppc_cached_irq_mask[n]); \ 54 ACK_UIC##n##_PARENT \ 55} \ 56 \ 57static void ppc4xx_uic##n##_ack(unsigned int irq) \ 58{ \ 59 u32 mask = IRQ_MASK_UIC##n(irq); \ 60 ppc_cached_irq_mask[n] &= ~mask; \ 61 mtdcr(DCRN_UIC_ER(UIC##n), ppc_cached_irq_mask[n]); \ 62 mtdcr(DCRN_UIC_SR(UIC##n), mask); \ 63 ACK_UIC##n##_PARENT \ 64} \ 65 \ 66static void ppc4xx_uic##n##_end(unsigned int irq) \ 67{ \ 68 unsigned int status = irq_desc[irq].status; \ 69 u32 mask = IRQ_MASK_UIC##n(irq); \ 70 if (status & IRQ_LEVEL) { \ 71 mtdcr(DCRN_UIC_SR(UIC##n), mask); \ 72 ACK_UIC##n##_PARENT \ 73 } \ 74 if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) { \ 75 ppc_cached_irq_mask[n] |= mask; \ 76 mtdcr(DCRN_UIC_ER(UIC##n), ppc_cached_irq_mask[n]); \ 77 } \ 78} 79 80#define DECLARE_UIC(n) \ 81{ \ 82 .typename = "UIC"#n, \ 83 .enable = ppc4xx_uic##n##_enable, \ 84 .disable = ppc4xx_uic##n##_disable, \ 85 .ack = ppc4xx_uic##n##_ack, \ 86 .end = ppc4xx_uic##n##_end, \ 87} \ 88 89#if NR_UICS == 4 90#define ACK_UIC0_PARENT 91#define ACK_UIC1_PARENT mtdcr(DCRN_UIC_SR(UIC0), UIC0_UIC1NC); 92#define ACK_UIC2_PARENT mtdcr(DCRN_UIC_SR(UIC0), UIC0_UIC2NC); 93#define ACK_UIC3_PARENT mtdcr(DCRN_UIC_SR(UIC0), UIC0_UIC3NC); 94UIC_HANDLERS(0); 95UIC_HANDLERS(1); 96UIC_HANDLERS(2); 97UIC_HANDLERS(3); 98 99static int ppc4xx_pic_get_irq(void) 100{ 101 u32 uic0 = mfdcr(DCRN_UIC_MSR(UIC0)); 102 if (uic0 & UIC0_UIC1NC) 103 return 64 - ffs(mfdcr(DCRN_UIC_MSR(UIC1))); 104 else if (uic0 & UIC0_UIC2NC) 105 return 96 - ffs(mfdcr(DCRN_UIC_MSR(UIC2))); 106 else if (uic0 & UIC0_UIC3NC) 107 return 128 - ffs(mfdcr(DCRN_UIC_MSR(UIC3))); 108 else 109 return uic0 ? 32 - ffs(uic0) : -1; 110} 111 112static void __init ppc4xx_pic_impl_init(void) 113{ 114 /* Enable cascade interrupts in UIC0 */ 115 ppc_cached_irq_mask[0] |= UIC0_UIC1NC | UIC0_UIC2NC | UIC0_UIC3NC; 116 mtdcr(DCRN_UIC_SR(UIC0), UIC0_UIC1NC | UIC0_UIC2NC | UIC0_UIC3NC); 117 mtdcr(DCRN_UIC_ER(UIC0), ppc_cached_irq_mask[0]); 118} 119 120#elif NR_UICS == 3 121#define ACK_UIC0_PARENT mtdcr(DCRN_UIC_SR(UICB), UICB_UIC0NC); 122#define ACK_UIC1_PARENT mtdcr(DCRN_UIC_SR(UICB), UICB_UIC1NC); 123#define ACK_UIC2_PARENT mtdcr(DCRN_UIC_SR(UICB), UICB_UIC2NC); 124UIC_HANDLERS(0); 125UIC_HANDLERS(1); 126UIC_HANDLERS(2); 127 128static int ppc4xx_pic_get_irq(void) 129{ 130 u32 uicb = mfdcr(DCRN_UIC_MSR(UICB)); 131 if (uicb & UICB_UIC0NC) 132 return 32 - ffs(mfdcr(DCRN_UIC_MSR(UIC0))); 133 else if (uicb & UICB_UIC1NC) 134 return 64 - ffs(mfdcr(DCRN_UIC_MSR(UIC1))); 135 else if (uicb & UICB_UIC2NC) 136 return 96 - ffs(mfdcr(DCRN_UIC_MSR(UIC2))); 137 else 138 return -1; 139} 140 141static void __init ppc4xx_pic_impl_init(void) 142{ 143#if defined(CONFIG_440GX) 144 /* Disable 440GP compatibility mode if it was enabled in firmware */ 145 SDR_WRITE(DCRN_SDR_MFR, SDR_READ(DCRN_SDR_MFR) & ~DCRN_SDR_MFR_PCM); 146#endif 147 /* Configure Base UIC */ 148 mtdcr(DCRN_UIC_CR(UICB), 0); 149 mtdcr(DCRN_UIC_TR(UICB), 0); 150 mtdcr(DCRN_UIC_PR(UICB), 0xffffffff); 151 mtdcr(DCRN_UIC_SR(UICB), 0xffffffff); 152 mtdcr(DCRN_UIC_ER(UICB), UICB_UIC0NC | UICB_UIC1NC | UICB_UIC2NC); 153} 154 155#elif NR_UICS == 2 156#define ACK_UIC0_PARENT 157#define ACK_UIC1_PARENT mtdcr(DCRN_UIC_SR(UIC0), UIC0_UIC1NC); 158UIC_HANDLERS(0); 159UIC_HANDLERS(1); 160 161static int ppc4xx_pic_get_irq(void) 162{ 163 u32 uic0 = mfdcr(DCRN_UIC_MSR(UIC0)); 164 if (uic0 & UIC0_UIC1NC) 165 return 64 - ffs(mfdcr(DCRN_UIC_MSR(UIC1))); 166 else 167 return uic0 ? 32 - ffs(uic0) : -1; 168} 169 170static void __init ppc4xx_pic_impl_init(void) 171{ 172 /* Enable cascade interrupt in UIC0 */ 173 ppc_cached_irq_mask[0] |= UIC0_UIC1NC; 174 mtdcr(DCRN_UIC_SR(UIC0), UIC0_UIC1NC); 175 mtdcr(DCRN_UIC_ER(UIC0), ppc_cached_irq_mask[0]); 176} 177 178#elif NR_UICS == 1 179#define ACK_UIC0_PARENT 180UIC_HANDLERS(0); 181 182static int ppc4xx_pic_get_irq(void) 183{ 184 u32 uic0 = mfdcr(DCRN_UIC_MSR(UIC0)); 185 return uic0 ? 32 - ffs(uic0) : -1; 186} 187 188static inline void ppc4xx_pic_impl_init(void) 189{ 190} 191#endif 192 193static struct ppc4xx_uic_impl { 194 struct hw_interrupt_type decl; 195 int base; /* Base DCR number */ 196} __uic[] = { 197 { .decl = DECLARE_UIC(0), .base = UIC0 }, 198#if NR_UICS > 1 199 { .decl = DECLARE_UIC(1), .base = UIC1 }, 200#if NR_UICS > 2 201 { .decl = DECLARE_UIC(2), .base = UIC2 }, 202#if NR_UICS > 3 203 { .decl = DECLARE_UIC(3), .base = UIC3 }, 204#endif 205#endif 206#endif 207}; 208 209static inline int is_level_sensitive(int irq) 210{ 211 u32 tr = mfdcr(DCRN_UIC_TR(__uic[irq >> 5].base)); 212 return (tr & IRQ_MASK_UICx(irq)) == 0; 213} 214 215void __init ppc4xx_pic_init(void) 216{ 217 int i; 218 unsigned char *eirqs = ppc4xx_uic_ext_irq_cfg; 219 220 for (i = 0; i < NR_UICS; ++i) { 221 int base = __uic[i].base; 222 223 /* Disable everything by default */ 224 ppc_cached_irq_mask[i] = 0; 225 mtdcr(DCRN_UIC_ER(base), 0); 226 227 /* We don't use critical interrupts */ 228 mtdcr(DCRN_UIC_CR(base), 0); 229 230 /* Configure polarity and triggering */ 231 if (ppc4xx_core_uic_cfg) { 232 struct ppc4xx_uic_settings *p = ppc4xx_core_uic_cfg + i; 233 u32 mask = p->ext_irq_mask; 234 u32 pr = mfdcr(DCRN_UIC_PR(base)) & mask; 235 u32 tr = mfdcr(DCRN_UIC_TR(base)) & mask; 236 237 /* "Fixed" interrupts (on-chip devices) */ 238 pr |= p->polarity & ~mask; 239 tr |= p->triggering & ~mask; 240 241 /* Merge external IRQs settings if board port 242 * provided them 243 */ 244 if (eirqs && mask) { 245 pr &= ~mask; 246 tr &= ~mask; 247 while (mask) { 248 /* Extract current external IRQ mask */ 249 u32 eirq_mask = 1 << __ilog2(mask); 250 251 if (!(*eirqs & IRQ_SENSE_LEVEL)) 252 tr |= eirq_mask; 253 254 if (*eirqs & IRQ_POLARITY_POSITIVE) 255 pr |= eirq_mask; 256 257 mask &= ~eirq_mask; 258 ++eirqs; 259 } 260 } 261 mtdcr(DCRN_UIC_PR(base), pr); 262 mtdcr(DCRN_UIC_TR(base), tr); 263 } 264 265 /* ACK any pending interrupts to prevent false 266 * triggering after first enable 267 */ 268 mtdcr(DCRN_UIC_SR(base), 0xffffffff); 269 } 270 271 /* Perform optional implementation specific setup 272 * (e.g. enable cascade interrupts for multi-UIC configurations) 273 */ 274 ppc4xx_pic_impl_init(); 275 276 /* Attach low-level handlers */ 277 for (i = 0; i < (NR_UICS << 5); ++i) { 278 irq_desc[i].chip = &__uic[i >> 5].decl; 279 if (is_level_sensitive(i)) 280 irq_desc[i].status |= IRQ_LEVEL; 281 } 282 283 ppc_md.get_irq = ppc4xx_pic_get_irq; 284} 285