diff options
| -rw-r--r-- | arch/powerpc/sysdev/Makefile | 4 | ||||
| -rw-r--r-- | arch/ppc/syslib/Makefile | 2 | ||||
| -rw-r--r-- | arch/ppc/syslib/ipic.c | 646 | ||||
| -rw-r--r-- | arch/ppc/syslib/ipic.h | 47 | ||||
| -rw-r--r-- | include/asm-powerpc/ipic.h | 12 |
5 files changed, 705 insertions, 6 deletions
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile index cebfae242602..e5e999ea891a 100644 --- a/arch/powerpc/sysdev/Makefile +++ b/arch/powerpc/sysdev/Makefile | |||
| @@ -9,11 +9,11 @@ obj-$(CONFIG_BOOKE) += dcr.o | |||
| 9 | obj-$(CONFIG_40x) += dcr.o | 9 | obj-$(CONFIG_40x) += dcr.o |
| 10 | obj-$(CONFIG_U3_DART) += dart_iommu.o | 10 | obj-$(CONFIG_U3_DART) += dart_iommu.o |
| 11 | obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o | 11 | obj-$(CONFIG_MMIO_NVRAM) += mmio_nvram.o |
| 12 | obj-$(CONFIG_PPC_83xx) += ipic.o | ||
| 13 | obj-$(CONFIG_FSL_SOC) += fsl_soc.o | 12 | obj-$(CONFIG_FSL_SOC) += fsl_soc.o |
| 14 | obj-$(CONFIG_PPC_TODC) += todc.o | 13 | obj-$(CONFIG_PPC_TODC) += todc.o |
| 15 | obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o | 14 | obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o |
| 16 | 15 | ||
| 17 | ifeq ($(CONFIG_PPC_MERGE),y) | 16 | ifeq ($(CONFIG_PPC_MERGE),y) |
| 18 | obj-$(CONFIG_PPC_I8259) += i8259.o | 17 | obj-$(CONFIG_PPC_I8259) += i8259.o |
| 19 | endif | 18 | obj-$(CONFIG_PPC_83xx) += ipic.o |
| 19 | endif | ||
diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile index 2497bbc07e76..dca23f2ef851 100644 --- a/arch/ppc/syslib/Makefile +++ b/arch/ppc/syslib/Makefile | |||
| @@ -93,7 +93,7 @@ obj-$(CONFIG_PCI) += pci_auto.o | |||
| 93 | endif | 93 | endif |
| 94 | obj-$(CONFIG_RAPIDIO) += ppc85xx_rio.o | 94 | obj-$(CONFIG_RAPIDIO) += ppc85xx_rio.o |
| 95 | obj-$(CONFIG_83xx) += ppc83xx_setup.o ppc_sys.o \ | 95 | obj-$(CONFIG_83xx) += ppc83xx_setup.o ppc_sys.o \ |
| 96 | mpc83xx_sys.o mpc83xx_devices.o | 96 | mpc83xx_sys.o mpc83xx_devices.o ipic.o |
| 97 | ifeq ($(CONFIG_83xx),y) | 97 | ifeq ($(CONFIG_83xx),y) |
| 98 | obj-$(CONFIG_PCI) += pci_auto.o | 98 | obj-$(CONFIG_PCI) += pci_auto.o |
| 99 | endif | 99 | endif |
diff --git a/arch/ppc/syslib/ipic.c b/arch/ppc/syslib/ipic.c new file mode 100644 index 000000000000..46801f5ec03f --- /dev/null +++ b/arch/ppc/syslib/ipic.c | |||
| @@ -0,0 +1,646 @@ | |||
| 1 | /* | ||
| 2 | * include/asm-ppc/ipic.c | ||
| 3 | * | ||
| 4 | * IPIC routines implementations. | ||
| 5 | * | ||
| 6 | * Copyright 2005 Freescale Semiconductor, Inc. | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify it | ||
| 9 | * under the terms of the GNU General Public License as published by the | ||
| 10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 11 | * option) any later version. | ||
| 12 | */ | ||
| 13 | #include <linux/kernel.h> | ||
| 14 | #include <linux/init.h> | ||
| 15 | #include <linux/errno.h> | ||
| 16 | #include <linux/reboot.h> | ||
| 17 | #include <linux/slab.h> | ||
| 18 | #include <linux/stddef.h> | ||
| 19 | #include <linux/sched.h> | ||
| 20 | #include <linux/signal.h> | ||
| 21 | #include <linux/sysdev.h> | ||
| 22 | #include <asm/irq.h> | ||
| 23 | #include <asm/io.h> | ||
| 24 | #include <asm/ipic.h> | ||
| 25 | #include <asm/mpc83xx.h> | ||
| 26 | |||
| 27 | #include "ipic.h" | ||
| 28 | |||
| 29 | static struct ipic p_ipic; | ||
| 30 | static struct ipic * primary_ipic; | ||
| 31 | |||
| 32 | static struct ipic_info ipic_info[] = { | ||
| 33 | [9] = { | ||
| 34 | .pend = IPIC_SIPNR_H, | ||
| 35 | .mask = IPIC_SIMSR_H, | ||
| 36 | .prio = IPIC_SIPRR_D, | ||
| 37 | .force = IPIC_SIFCR_H, | ||
| 38 | .bit = 24, | ||
| 39 | .prio_mask = 0, | ||
| 40 | }, | ||
| 41 | [10] = { | ||
| 42 | .pend = IPIC_SIPNR_H, | ||
| 43 | .mask = IPIC_SIMSR_H, | ||
| 44 | .prio = IPIC_SIPRR_D, | ||
| 45 | .force = IPIC_SIFCR_H, | ||
| 46 | .bit = 25, | ||
| 47 | .prio_mask = 1, | ||
| 48 | }, | ||
| 49 | [11] = { | ||
| 50 | .pend = IPIC_SIPNR_H, | ||
| 51 | .mask = IPIC_SIMSR_H, | ||
| 52 | .prio = IPIC_SIPRR_D, | ||
| 53 | .force = IPIC_SIFCR_H, | ||
| 54 | .bit = 26, | ||
| 55 | .prio_mask = 2, | ||
| 56 | }, | ||
| 57 | [14] = { | ||
| 58 | .pend = IPIC_SIPNR_H, | ||
| 59 | .mask = IPIC_SIMSR_H, | ||
| 60 | .prio = IPIC_SIPRR_D, | ||
| 61 | .force = IPIC_SIFCR_H, | ||
| 62 | .bit = 29, | ||
| 63 | .prio_mask = 5, | ||
| 64 | }, | ||
| 65 | [15] = { | ||
| 66 | .pend = IPIC_SIPNR_H, | ||
| 67 | .mask = IPIC_SIMSR_H, | ||
| 68 | .prio = IPIC_SIPRR_D, | ||
| 69 | .force = IPIC_SIFCR_H, | ||
| 70 | .bit = 30, | ||
| 71 | .prio_mask = 6, | ||
| 72 | }, | ||
| 73 | [16] = { | ||
| 74 | .pend = IPIC_SIPNR_H, | ||
| 75 | .mask = IPIC_SIMSR_H, | ||
| 76 | .prio = IPIC_SIPRR_D, | ||
| 77 | .force = IPIC_SIFCR_H, | ||
| 78 | .bit = 31, | ||
| 79 | .prio_mask = 7, | ||
| 80 | }, | ||
| 81 | [17] = { | ||
| 82 | .pend = IPIC_SEPNR, | ||
| 83 | .mask = IPIC_SEMSR, | ||
| 84 | .prio = IPIC_SMPRR_A, | ||
| 85 | .force = IPIC_SEFCR, | ||
| 86 | .bit = 1, | ||
| 87 | .prio_mask = 5, | ||
| 88 | }, | ||
| 89 | [18] = { | ||
| 90 | .pend = IPIC_SEPNR, | ||
| 91 | .mask = IPIC_SEMSR, | ||
| 92 | .prio = IPIC_SMPRR_A, | ||
| 93 | .force = IPIC_SEFCR, | ||
| 94 | .bit = 2, | ||
| 95 | .prio_mask = 6, | ||
| 96 | }, | ||
| 97 | [19] = { | ||
| 98 | .pend = IPIC_SEPNR, | ||
| 99 | .mask = IPIC_SEMSR, | ||
| 100 | .prio = IPIC_SMPRR_A, | ||
| 101 | .force = IPIC_SEFCR, | ||
| 102 | .bit = 3, | ||
| 103 | .prio_mask = 7, | ||
| 104 | }, | ||
| 105 | [20] = { | ||
| 106 | .pend = IPIC_SEPNR, | ||
| 107 | .mask = IPIC_SEMSR, | ||
| 108 | .prio = IPIC_SMPRR_B, | ||
| 109 | .force = IPIC_SEFCR, | ||
| 110 | .bit = 4, | ||
| 111 | .prio_mask = 4, | ||
| 112 | }, | ||
| 113 | [21] = { | ||
| 114 | .pend = IPIC_SEPNR, | ||
| 115 | .mask = IPIC_SEMSR, | ||
| 116 | .prio = IPIC_SMPRR_B, | ||
| 117 | .force = IPIC_SEFCR, | ||
| 118 | .bit = 5, | ||
| 119 | .prio_mask = 5, | ||
| 120 | }, | ||
| 121 | [22] = { | ||
| 122 | .pend = IPIC_SEPNR, | ||
| 123 | .mask = IPIC_SEMSR, | ||
| 124 | .prio = IPIC_SMPRR_B, | ||
| 125 | .force = IPIC_SEFCR, | ||
| 126 | .bit = 6, | ||
| 127 | .prio_mask = 6, | ||
| 128 | }, | ||
| 129 | [23] = { | ||
| 130 | .pend = IPIC_SEPNR, | ||
| 131 | .mask = IPIC_SEMSR, | ||
| 132 | .prio = IPIC_SMPRR_B, | ||
| 133 | .force = IPIC_SEFCR, | ||
| 134 | .bit = 7, | ||
| 135 | .prio_mask = 7, | ||
| 136 | }, | ||
| 137 | [32] = { | ||
| 138 | .pend = IPIC_SIPNR_H, | ||
| 139 | .mask = IPIC_SIMSR_H, | ||
| 140 | .prio = IPIC_SIPRR_A, | ||
| 141 | .force = IPIC_SIFCR_H, | ||
| 142 | .bit = 0, | ||
| 143 | .prio_mask = 0, | ||
| 144 | }, | ||
| 145 | [33] = { | ||
| 146 | .pend = IPIC_SIPNR_H, | ||
| 147 | .mask = IPIC_SIMSR_H, | ||
| 148 | .prio = IPIC_SIPRR_A, | ||
| 149 | .force = IPIC_SIFCR_H, | ||
| 150 | .bit = 1, | ||
| 151 | .prio_mask = 1, | ||
| 152 | }, | ||
| 153 | [34] = { | ||
| 154 | .pend = IPIC_SIPNR_H, | ||
| 155 | .mask = IPIC_SIMSR_H, | ||
| 156 | .prio = IPIC_SIPRR_A, | ||
| 157 | .force = IPIC_SIFCR_H, | ||
| 158 | .bit = 2, | ||
| 159 | .prio_mask = 2, | ||
| 160 | }, | ||
| 161 | [35] = { | ||
| 162 | .pend = IPIC_SIPNR_H, | ||
| 163 | .mask = IPIC_SIMSR_H, | ||
| 164 | .prio = IPIC_SIPRR_A, | ||
| 165 | .force = IPIC_SIFCR_H, | ||
| 166 | .bit = 3, | ||
| 167 | .prio_mask = 3, | ||
| 168 | }, | ||
| 169 | [36] = { | ||
| 170 | .pend = IPIC_SIPNR_H, | ||
| 171 | .mask = IPIC_SIMSR_H, | ||
| 172 | .prio = IPIC_SIPRR_A, | ||
| 173 | .force = IPIC_SIFCR_H, | ||
| 174 | .bit = 4, | ||
| 175 | .prio_mask = 4, | ||
| 176 | }, | ||
| 177 | [37] = { | ||
| 178 | .pend = IPIC_SIPNR_H, | ||
| 179 | .mask = IPIC_SIMSR_H, | ||
| 180 | .prio = IPIC_SIPRR_A, | ||
| 181 | .force = IPIC_SIFCR_H, | ||
| 182 | .bit = 5, | ||
| 183 | .prio_mask = 5, | ||
| 184 | }, | ||
| 185 | [38] = { | ||
| 186 | .pend = IPIC_SIPNR_H, | ||
| 187 | .mask = IPIC_SIMSR_H, | ||
| 188 | .prio = IPIC_SIPRR_A, | ||
| 189 | .force = IPIC_SIFCR_H, | ||
| 190 | .bit = 6, | ||
| 191 | .prio_mask = 6, | ||
| 192 | }, | ||
| 193 | [39] = { | ||
| 194 | .pend = IPIC_SIPNR_H, | ||
| 195 | .mask = IPIC_SIMSR_H, | ||
| 196 | .prio = IPIC_SIPRR_A, | ||
| 197 | .force = IPIC_SIFCR_H, | ||
| 198 | .bit = 7, | ||
| 199 | .prio_mask = 7, | ||
| 200 | }, | ||
| 201 | [48] = { | ||
| 202 | .pend = IPIC_SEPNR, | ||
| 203 | .mask = IPIC_SEMSR, | ||
| 204 | .prio = IPIC_SMPRR_A, | ||
| 205 | .force = IPIC_SEFCR, | ||
| 206 | .bit = 0, | ||
| 207 | .prio_mask = 4, | ||
| 208 | }, | ||
| 209 | [64] = { | ||
| 210 | .pend = IPIC_SIPNR_H, | ||
| 211 | .mask = IPIC_SIMSR_L, | ||
| 212 | .prio = IPIC_SMPRR_A, | ||
| 213 | .force = IPIC_SIFCR_L, | ||
| 214 | .bit = 0, | ||
| 215 | .prio_mask = 0, | ||
| 216 | }, | ||
| 217 | [65] = { | ||
| 218 | .pend = IPIC_SIPNR_H, | ||
| 219 | .mask = IPIC_SIMSR_L, | ||
| 220 | .prio = IPIC_SMPRR_A, | ||
| 221 | .force = IPIC_SIFCR_L, | ||
| 222 | .bit = 1, | ||
| 223 | .prio_mask = 1, | ||
| 224 | }, | ||
| 225 | [66] = { | ||
| 226 | .pend = IPIC_SIPNR_H, | ||
| 227 | .mask = IPIC_SIMSR_L, | ||
| 228 | .prio = IPIC_SMPRR_A, | ||
| 229 | .force = IPIC_SIFCR_L, | ||
| 230 | .bit = 2, | ||
| 231 | .prio_mask = 2, | ||
| 232 | }, | ||
| 233 | [67] = { | ||
| 234 | .pend = IPIC_SIPNR_H, | ||
| 235 | .mask = IPIC_SIMSR_L, | ||
| 236 | .prio = IPIC_SMPRR_A, | ||
| 237 | .force = IPIC_SIFCR_L, | ||
| 238 | .bit = 3, | ||
| 239 | .prio_mask = 3, | ||
| 240 | }, | ||
| 241 | [68] = { | ||
| 242 | .pend = IPIC_SIPNR_H, | ||
| 243 | .mask = IPIC_SIMSR_L, | ||
| 244 | .prio = IPIC_SMPRR_B, | ||
| 245 | .force = IPIC_SIFCR_L, | ||
| 246 | .bit = 4, | ||
| 247 | .prio_mask = 0, | ||
| 248 | }, | ||
| 249 | [69] = { | ||
| 250 | .pend = IPIC_SIPNR_H, | ||
| 251 | .mask = IPIC_SIMSR_L, | ||
| 252 | .prio = IPIC_SMPRR_B, | ||
| 253 | .force = IPIC_SIFCR_L, | ||
| 254 | .bit = 5, | ||
| 255 | .prio_mask = 1, | ||
| 256 | }, | ||
| 257 | [70] = { | ||
| 258 | .pend = IPIC_SIPNR_H, | ||
| 259 | .mask = IPIC_SIMSR_L, | ||
| 260 | .prio = IPIC_SMPRR_B, | ||
| 261 | .force = IPIC_SIFCR_L, | ||
| 262 | .bit = 6, | ||
| 263 | .prio_mask = 2, | ||
| 264 | }, | ||
| 265 | [71] = { | ||
| 266 | .pend = IPIC_SIPNR_H, | ||
| 267 | .mask = IPIC_SIMSR_L, | ||
| 268 | .prio = IPIC_SMPRR_B, | ||
| 269 | .force = IPIC_SIFCR_L, | ||
| 270 | .bit = 7, | ||
| 271 | .prio_mask = 3, | ||
| 272 | }, | ||
| 273 | [72] = { | ||
| 274 | .pend = IPIC_SIPNR_H, | ||
| 275 | .mask = IPIC_SIMSR_L, | ||
| 276 | .prio = 0, | ||
| 277 | .force = IPIC_SIFCR_L, | ||
| 278 | .bit = 8, | ||
| 279 | }, | ||
| 280 | [73] = { | ||
| 281 | .pend = IPIC_SIPNR_H, | ||
| 282 | .mask = IPIC_SIMSR_L, | ||
| 283 | .prio = 0, | ||
| 284 | .force = IPIC_SIFCR_L, | ||
| 285 | .bit = 9, | ||
| 286 | }, | ||
| 287 | [74] = { | ||
| 288 | .pend = IPIC_SIPNR_H, | ||
| 289 | .mask = IPIC_SIMSR_L, | ||
| 290 | .prio = 0, | ||
| 291 | .force = IPIC_SIFCR_L, | ||
| 292 | .bit = 10, | ||
| 293 | }, | ||
| 294 | [75] = { | ||
| 295 | .pend = IPIC_SIPNR_H, | ||
| 296 | .mask = IPIC_SIMSR_L, | ||
| 297 | .prio = 0, | ||
| 298 | .force = IPIC_SIFCR_L, | ||
| 299 | .bit = 11, | ||
| 300 | }, | ||
| 301 | [76] = { | ||
| 302 | .pend = IPIC_SIPNR_H, | ||
| 303 | .mask = IPIC_SIMSR_L, | ||
| 304 | .prio = 0, | ||
| 305 | .force = IPIC_SIFCR_L, | ||
| 306 | .bit = 12, | ||
| 307 | }, | ||
| 308 | [77] = { | ||
| 309 | .pend = IPIC_SIPNR_H, | ||
| 310 | .mask = IPIC_SIMSR_L, | ||
| 311 | .prio = 0, | ||
| 312 | .force = IPIC_SIFCR_L, | ||
| 313 | .bit = 13, | ||
| 314 | }, | ||
| 315 | [78] = { | ||
| 316 | .pend = IPIC_SIPNR_H, | ||
| 317 | .mask = IPIC_SIMSR_L, | ||
| 318 | .prio = 0, | ||
| 319 | .force = IPIC_SIFCR_L, | ||
| 320 | .bit = 14, | ||
| 321 | }, | ||
| 322 | [79] = { | ||
| 323 | .pend = IPIC_SIPNR_H, | ||
| 324 | .mask = IPIC_SIMSR_L, | ||
| 325 | .prio = 0, | ||
| 326 | .force = IPIC_SIFCR_L, | ||
| 327 | .bit = 15, | ||
| 328 | }, | ||
| 329 | [80] = { | ||
| 330 | .pend = IPIC_SIPNR_H, | ||
| 331 | .mask = IPIC_SIMSR_L, | ||
| 332 | .prio = 0, | ||
| 333 | .force = IPIC_SIFCR_L, | ||
| 334 | .bit = 16, | ||
| 335 | }, | ||
| 336 | [84] = { | ||
| 337 | .pend = IPIC_SIPNR_H, | ||
| 338 | .mask = IPIC_SIMSR_L, | ||
| 339 | .prio = 0, | ||
| 340 | .force = IPIC_SIFCR_L, | ||
| 341 | .bit = 20, | ||
| 342 | }, | ||
| 343 | [85] = { | ||
| 344 | .pend = IPIC_SIPNR_H, | ||
| 345 | .mask = IPIC_SIMSR_L, | ||
| 346 | .prio = 0, | ||
| 347 | .force = IPIC_SIFCR_L, | ||
| 348 | .bit = 21, | ||
| 349 | }, | ||
| 350 | [90] = { | ||
| 351 | .pend = IPIC_SIPNR_H, | ||
| 352 | .mask = IPIC_SIMSR_L, | ||
| 353 | .prio = 0, | ||
| 354 | .force = IPIC_SIFCR_L, | ||
| 355 | .bit = 26, | ||
| 356 | }, | ||
| 357 | [91] = { | ||
| 358 | .pend = IPIC_SIPNR_H, | ||
| 359 | .mask = IPIC_SIMSR_L, | ||
| 360 | .prio = 0, | ||
| 361 | .force = IPIC_SIFCR_L, | ||
| 362 | .bit = 27, | ||
| 363 | }, | ||
| 364 | }; | ||
| 365 | |||
| 366 | static inline u32 ipic_read(volatile u32 __iomem *base, unsigned int reg) | ||
| 367 | { | ||
| 368 | return in_be32(base + (reg >> 2)); | ||
| 369 | } | ||
| 370 | |||
| 371 | static inline void ipic_write(volatile u32 __iomem *base, unsigned int reg, u32 value) | ||
| 372 | { | ||
| 373 | out_be32(base + (reg >> 2), value); | ||
| 374 | } | ||
| 375 | |||
| 376 | static inline struct ipic * ipic_from_irq(unsigned int irq) | ||
| 377 | { | ||
| 378 | return primary_ipic; | ||
| 379 | } | ||
| 380 | |||
| 381 | static void ipic_enable_irq(unsigned int irq) | ||
| 382 | { | ||
| 383 | struct ipic *ipic = ipic_from_irq(irq); | ||
| 384 | unsigned int src = irq - ipic->irq_offset; | ||
| 385 | u32 temp; | ||
| 386 | |||
| 387 | temp = ipic_read(ipic->regs, ipic_info[src].mask); | ||
| 388 | temp |= (1 << (31 - ipic_info[src].bit)); | ||
| 389 | ipic_write(ipic->regs, ipic_info[src].mask, temp); | ||
| 390 | } | ||
| 391 | |||
| 392 | static void ipic_disable_irq(unsigned int irq) | ||
| 393 | { | ||
| 394 | struct ipic *ipic = ipic_from_irq(irq); | ||
| 395 | unsigned int src = irq - ipic->irq_offset; | ||
| 396 | u32 temp; | ||
| 397 | |||
| 398 | temp = ipic_read(ipic->regs, ipic_info[src].mask); | ||
| 399 | temp &= ~(1 << (31 - ipic_info[src].bit)); | ||
| 400 | ipic_write(ipic->regs, ipic_info[src].mask, temp); | ||
| 401 | } | ||
| 402 | |||
| 403 | static void ipic_disable_irq_and_ack(unsigned int irq) | ||
| 404 | { | ||
| 405 | struct ipic *ipic = ipic_from_irq(irq); | ||
| 406 | unsigned int src = irq - ipic->irq_offset; | ||
| 407 | u32 temp; | ||
| 408 | |||
| 409 | ipic_disable_irq(irq); | ||
| 410 | |||
| 411 | temp = ipic_read(ipic->regs, ipic_info[src].pend); | ||
| 412 | temp |= (1 << (31 - ipic_info[src].bit)); | ||
| 413 | ipic_write(ipic->regs, ipic_info[src].pend, temp); | ||
| 414 | } | ||
| 415 | |||
| 416 | static void ipic_end_irq(unsigned int irq) | ||
| 417 | { | ||
| 418 | if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) | ||
| 419 | ipic_enable_irq(irq); | ||
| 420 | } | ||
| 421 | |||
| 422 | struct hw_interrupt_type ipic = { | ||
| 423 | .typename = " IPIC ", | ||
| 424 | .enable = ipic_enable_irq, | ||
| 425 | .disable = ipic_disable_irq, | ||
| 426 | .ack = ipic_disable_irq_and_ack, | ||
| 427 | .end = ipic_end_irq, | ||
| 428 | }; | ||
| 429 | |||
| 430 | void __init ipic_init(phys_addr_t phys_addr, | ||
| 431 | unsigned int flags, | ||
| 432 | unsigned int irq_offset, | ||
| 433 | unsigned char *senses, | ||
| 434 | unsigned int senses_count) | ||
| 435 | { | ||
| 436 | u32 i, temp = 0; | ||
| 437 | |||
| 438 | primary_ipic = &p_ipic; | ||
| 439 | primary_ipic->regs = ioremap(phys_addr, MPC83xx_IPIC_SIZE); | ||
| 440 | |||
| 441 | primary_ipic->irq_offset = irq_offset; | ||
| 442 | |||
| 443 | ipic_write(primary_ipic->regs, IPIC_SICNR, 0x0); | ||
| 444 | |||
| 445 | /* default priority scheme is grouped. If spread mode is required | ||
| 446 | * configure SICFR accordingly */ | ||
| 447 | if (flags & IPIC_SPREADMODE_GRP_A) | ||
| 448 | temp |= SICFR_IPSA; | ||
| 449 | if (flags & IPIC_SPREADMODE_GRP_D) | ||
| 450 | temp |= SICFR_IPSD; | ||
| 451 | if (flags & IPIC_SPREADMODE_MIX_A) | ||
| 452 | temp |= SICFR_MPSA; | ||
| 453 | if (flags & IPIC_SPREADMODE_MIX_B) | ||
| 454 | temp |= SICFR_MPSB; | ||
| 455 | |||
| 456 | ipic_write(primary_ipic->regs, IPIC_SICNR, temp); | ||
| 457 | |||
| 458 | /* handle MCP route */ | ||
| 459 | temp = 0; | ||
| 460 | if (flags & IPIC_DISABLE_MCP_OUT) | ||
| 461 | temp = SERCR_MCPR; | ||
| 462 | ipic_write(primary_ipic->regs, IPIC_SERCR, temp); | ||
| 463 | |||
| 464 | /* handle routing of IRQ0 to MCP */ | ||
| 465 | temp = ipic_read(primary_ipic->regs, IPIC_SEMSR); | ||
| 466 | |||
| 467 | if (flags & IPIC_IRQ0_MCP) | ||
| 468 | temp |= SEMSR_SIRQ0; | ||
| 469 | else | ||
| 470 | temp &= ~SEMSR_SIRQ0; | ||
| 471 | |||
| 472 | ipic_write(primary_ipic->regs, IPIC_SEMSR, temp); | ||
| 473 | |||
| 474 | for (i = 0 ; i < NR_IPIC_INTS ; i++) { | ||
| 475 | irq_desc[i+irq_offset].chip = &ipic; | ||
| 476 | irq_desc[i+irq_offset].status = IRQ_LEVEL; | ||
| 477 | } | ||
| 478 | |||
| 479 | temp = 0; | ||
| 480 | for (i = 0 ; i < senses_count ; i++) { | ||
| 481 | if ((senses[i] & IRQ_SENSE_MASK) == IRQ_SENSE_EDGE) { | ||
| 482 | temp |= 1 << (15 - i); | ||
| 483 | if (i != 0) | ||
| 484 | irq_desc[i + irq_offset + MPC83xx_IRQ_EXT1 - 1].status = 0; | ||
| 485 | else | ||
| 486 | irq_desc[irq_offset + MPC83xx_IRQ_EXT0].status = 0; | ||
| 487 | } | ||
| 488 | } | ||
| 489 | ipic_write(primary_ipic->regs, IPIC_SECNR, temp); | ||
| 490 | |||
| 491 | printk ("IPIC (%d IRQ sources, %d External IRQs) at %p\n", NR_IPIC_INTS, | ||
| 492 | senses_count, primary_ipic->regs); | ||
| 493 | } | ||
| 494 | |||
| 495 | int ipic_set_priority(unsigned int irq, unsigned int priority) | ||
| 496 | { | ||
| 497 | struct ipic *ipic = ipic_from_irq(irq); | ||
| 498 | unsigned int src = irq - ipic->irq_offset; | ||
| 499 | u32 temp; | ||
| 500 | |||
| 501 | if (priority > 7) | ||
| 502 | return -EINVAL; | ||
| 503 | if (src > 127) | ||
| 504 | return -EINVAL; | ||
| 505 | if (ipic_info[src].prio == 0) | ||
| 506 | return -EINVAL; | ||
| 507 | |||
| 508 | temp = ipic_read(ipic->regs, ipic_info[src].prio); | ||
| 509 | |||
| 510 | if (priority < 4) { | ||
| 511 | temp &= ~(0x7 << (20 + (3 - priority) * 3)); | ||
| 512 | temp |= ipic_info[src].prio_mask << (20 + (3 - priority) * 3); | ||
| 513 | } else { | ||
| 514 | temp &= ~(0x7 << (4 + (7 - priority) * 3)); | ||
| 515 | temp |= ipic_info[src].prio_mask << (4 + (7 - priority) * 3); | ||
| 516 | } | ||
| 517 | |||
| 518 | ipic_write(ipic->regs, ipic_info[src].prio, temp); | ||
| 519 | |||
| 520 | return 0; | ||
| 521 | } | ||
| 522 | |||
| 523 | void ipic_set_highest_priority(unsigned int irq) | ||
| 524 | { | ||
| 525 | struct ipic *ipic = ipic_from_irq(irq); | ||
| 526 | unsigned int src = irq - ipic->irq_offset; | ||
| 527 | u32 temp; | ||
| 528 | |||
| 529 | temp = ipic_read(ipic->regs, IPIC_SICFR); | ||
| 530 | |||
| 531 | /* clear and set HPI */ | ||
| 532 | temp &= 0x7f000000; | ||
| 533 | temp |= (src & 0x7f) << 24; | ||
| 534 | |||
| 535 | ipic_write(ipic->regs, IPIC_SICFR, temp); | ||
| 536 | } | ||
| 537 | |||
| 538 | void ipic_set_default_priority(void) | ||
| 539 | { | ||
| 540 | ipic_set_priority(MPC83xx_IRQ_TSEC1_TX, 0); | ||
| 541 | ipic_set_priority(MPC83xx_IRQ_TSEC1_RX, 1); | ||
| 542 | ipic_set_priority(MPC83xx_IRQ_TSEC1_ERROR, 2); | ||
| 543 | ipic_set_priority(MPC83xx_IRQ_TSEC2_TX, 3); | ||
| 544 | ipic_set_priority(MPC83xx_IRQ_TSEC2_RX, 4); | ||
| 545 | ipic_set_priority(MPC83xx_IRQ_TSEC2_ERROR, 5); | ||
| 546 | ipic_set_priority(MPC83xx_IRQ_USB2_DR, 6); | ||
| 547 | ipic_set_priority(MPC83xx_IRQ_USB2_MPH, 7); | ||
| 548 | |||
| 549 | ipic_set_priority(MPC83xx_IRQ_UART1, 0); | ||
| 550 | ipic_set_priority(MPC83xx_IRQ_UART2, 1); | ||
| 551 | ipic_set_priority(MPC83xx_IRQ_SEC2, 2); | ||
| 552 | ipic_set_priority(MPC83xx_IRQ_IIC1, 5); | ||
| 553 | ipic_set_priority(MPC83xx_IRQ_IIC2, 6); | ||
| 554 | ipic_set_priority(MPC83xx_IRQ_SPI, 7); | ||
| 555 | ipic_set_priority(MPC83xx_IRQ_RTC_SEC, 0); | ||
| 556 | ipic_set_priority(MPC83xx_IRQ_PIT, 1); | ||
| 557 | ipic_set_priority(MPC83xx_IRQ_PCI1, 2); | ||
| 558 | ipic_set_priority(MPC83xx_IRQ_PCI2, 3); | ||
| 559 | ipic_set_priority(MPC83xx_IRQ_EXT0, 4); | ||
| 560 | ipic_set_priority(MPC83xx_IRQ_EXT1, 5); | ||
| 561 | ipic_set_priority(MPC83xx_IRQ_EXT2, 6); | ||
| 562 | ipic_set_priority(MPC83xx_IRQ_EXT3, 7); | ||
| 563 | ipic_set_priority(MPC83xx_IRQ_RTC_ALR, 0); | ||
| 564 | ipic_set_priority(MPC83xx_IRQ_MU, 1); | ||
| 565 | ipic_set_priority(MPC83xx_IRQ_SBA, 2); | ||
| 566 | ipic_set_priority(MPC83xx_IRQ_DMA, 3); | ||
| 567 | ipic_set_priority(MPC83xx_IRQ_EXT4, 4); | ||
| 568 | ipic_set_priority(MPC83xx_IRQ_EXT5, 5); | ||
| 569 | ipic_set_priority(MPC83xx_IRQ_EXT6, 6); | ||
| 570 | ipic_set_priority(MPC83xx_IRQ_EXT7, 7); | ||
| 571 | } | ||
| 572 | |||
| 573 | void ipic_enable_mcp(enum ipic_mcp_irq mcp_irq) | ||
| 574 | { | ||
| 575 | struct ipic *ipic = primary_ipic; | ||
| 576 | u32 temp; | ||
| 577 | |||
| 578 | temp = ipic_read(ipic->regs, IPIC_SERMR); | ||
| 579 | temp |= (1 << (31 - mcp_irq)); | ||
| 580 | ipic_write(ipic->regs, IPIC_SERMR, temp); | ||
| 581 | } | ||
| 582 | |||
| 583 | void ipic_disable_mcp(enum ipic_mcp_irq mcp_irq) | ||
| 584 | { | ||
| 585 | struct ipic *ipic = primary_ipic; | ||
| 586 | u32 temp; | ||
| 587 | |||
| 588 | temp = ipic_read(ipic->regs, IPIC_SERMR); | ||
| 589 | temp &= (1 << (31 - mcp_irq)); | ||
| 590 | ipic_write(ipic->regs, IPIC_SERMR, temp); | ||
| 591 | } | ||
| 592 | |||
| 593 | u32 ipic_get_mcp_status(void) | ||
| 594 | { | ||
| 595 | return ipic_read(primary_ipic->regs, IPIC_SERMR); | ||
| 596 | } | ||
| 597 | |||
| 598 | void ipic_clear_mcp_status(u32 mask) | ||
| 599 | { | ||
| 600 | ipic_write(primary_ipic->regs, IPIC_SERMR, mask); | ||
| 601 | } | ||
| 602 | |||
| 603 | /* Return an interrupt vector or -1 if no interrupt is pending. */ | ||
| 604 | int ipic_get_irq(struct pt_regs *regs) | ||
| 605 | { | ||
| 606 | int irq; | ||
| 607 | |||
| 608 | irq = ipic_read(primary_ipic->regs, IPIC_SIVCR) & 0x7f; | ||
| 609 | |||
| 610 | if (irq == 0) /* 0 --> no irq is pending */ | ||
| 611 | irq = -1; | ||
| 612 | |||
| 613 | return irq; | ||
| 614 | } | ||
| 615 | |||
| 616 | static struct sysdev_class ipic_sysclass = { | ||
| 617 | set_kset_name("ipic"), | ||
| 618 | }; | ||
| 619 | |||
| 620 | static struct sys_device device_ipic = { | ||
| 621 | .id = 0, | ||
| 622 | .cls = &ipic_sysclass, | ||
| 623 | }; | ||
| 624 | |||
| 625 | static int __init init_ipic_sysfs(void) | ||
| 626 | { | ||
| 627 | int rc; | ||
| 628 | |||
| 629 | if (!primary_ipic->regs) | ||
| 630 | return -ENODEV; | ||
| 631 | printk(KERN_DEBUG "Registering ipic with sysfs...\n"); | ||
| 632 | |||
| 633 | rc = sysdev_class_register(&ipic_sysclass); | ||
| 634 | if (rc) { | ||
| 635 | printk(KERN_ERR "Failed registering ipic sys class\n"); | ||
| 636 | return -ENODEV; | ||
| 637 | } | ||
| 638 | rc = sysdev_register(&device_ipic); | ||
| 639 | if (rc) { | ||
| 640 | printk(KERN_ERR "Failed registering ipic sys device\n"); | ||
| 641 | return -ENODEV; | ||
| 642 | } | ||
| 643 | return 0; | ||
| 644 | } | ||
| 645 | |||
| 646 | subsys_initcall(init_ipic_sysfs); | ||
diff --git a/arch/ppc/syslib/ipic.h b/arch/ppc/syslib/ipic.h new file mode 100644 index 000000000000..a60c9d18bb7f --- /dev/null +++ b/arch/ppc/syslib/ipic.h | |||
| @@ -0,0 +1,47 @@ | |||
| 1 | /* | ||
| 2 | * IPIC private definitions and structure. | ||
| 3 | * | ||
| 4 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> | ||
| 5 | * | ||
| 6 | * Copyright 2005 Freescale Semiconductor, Inc | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify it | ||
| 9 | * under the terms of the GNU General Public License as published by the | ||
| 10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 11 | * option) any later version. | ||
| 12 | */ | ||
| 13 | #ifndef __IPIC_H__ | ||
| 14 | #define __IPIC_H__ | ||
| 15 | |||
| 16 | #include <asm/ipic.h> | ||
| 17 | |||
| 18 | #define MPC83xx_IPIC_SIZE (0x00100) | ||
| 19 | |||
| 20 | /* System Global Interrupt Configuration Register */ | ||
| 21 | #define SICFR_IPSA 0x00010000 | ||
| 22 | #define SICFR_IPSD 0x00080000 | ||
| 23 | #define SICFR_MPSA 0x00200000 | ||
| 24 | #define SICFR_MPSB 0x00400000 | ||
| 25 | |||
| 26 | /* System External Interrupt Mask Register */ | ||
| 27 | #define SEMSR_SIRQ0 0x00008000 | ||
| 28 | |||
| 29 | /* System Error Control Register */ | ||
| 30 | #define SERCR_MCPR 0x00000001 | ||
| 31 | |||
| 32 | struct ipic { | ||
| 33 | volatile u32 __iomem *regs; | ||
| 34 | unsigned int irq_offset; | ||
| 35 | }; | ||
| 36 | |||
| 37 | struct ipic_info { | ||
| 38 | u8 pend; /* pending register offset from base */ | ||
| 39 | u8 mask; /* mask register offset from base */ | ||
| 40 | u8 prio; /* priority register offset from base */ | ||
| 41 | u8 force; /* force register offset from base */ | ||
| 42 | u8 bit; /* register bit position (as per doc) | ||
| 43 | bit mask = 1 << (31 - bit) */ | ||
| 44 | u8 prio_mask; /* priority mask value */ | ||
| 45 | }; | ||
| 46 | |||
| 47 | #endif /* __IPIC_H__ */ | ||
diff --git a/include/asm-powerpc/ipic.h b/include/asm-powerpc/ipic.h index 0fe396a2b666..53079ec3a515 100644 --- a/include/asm-powerpc/ipic.h +++ b/include/asm-powerpc/ipic.h | |||
| @@ -69,9 +69,6 @@ enum ipic_mcp_irq { | |||
| 69 | IPIC_MCP_MU = 7, | 69 | IPIC_MCP_MU = 7, |
| 70 | }; | 70 | }; |
| 71 | 71 | ||
| 72 | extern void ipic_init(phys_addr_t phys_addr, unsigned int flags, | ||
| 73 | unsigned int irq_offset, | ||
| 74 | unsigned char *senses, unsigned int senses_count); | ||
| 75 | extern int ipic_set_priority(unsigned int irq, unsigned int priority); | 72 | extern int ipic_set_priority(unsigned int irq, unsigned int priority); |
| 76 | extern void ipic_set_highest_priority(unsigned int irq); | 73 | extern void ipic_set_highest_priority(unsigned int irq); |
| 77 | extern void ipic_set_default_priority(void); | 74 | extern void ipic_set_default_priority(void); |
| @@ -79,7 +76,16 @@ extern void ipic_enable_mcp(enum ipic_mcp_irq mcp_irq); | |||
| 79 | extern void ipic_disable_mcp(enum ipic_mcp_irq mcp_irq); | 76 | extern void ipic_disable_mcp(enum ipic_mcp_irq mcp_irq); |
| 80 | extern u32 ipic_get_mcp_status(void); | 77 | extern u32 ipic_get_mcp_status(void); |
| 81 | extern void ipic_clear_mcp_status(u32 mask); | 78 | extern void ipic_clear_mcp_status(u32 mask); |
| 79 | |||
| 80 | #ifdef CONFIG_PPC_MERGE | ||
| 81 | extern void ipic_init(struct device_node *node, unsigned int flags); | ||
| 82 | extern unsigned int ipic_get_irq(struct pt_regs *regs); | ||
| 83 | #else | ||
| 84 | extern void ipic_init(phys_addr_t phys_addr, unsigned int flags, | ||
| 85 | unsigned int irq_offset, | ||
| 86 | unsigned char *senses, unsigned int senses_count); | ||
| 82 | extern int ipic_get_irq(struct pt_regs *regs); | 87 | extern int ipic_get_irq(struct pt_regs *regs); |
| 88 | #endif | ||
| 83 | 89 | ||
| 84 | #endif /* __ASM_IPIC_H__ */ | 90 | #endif /* __ASM_IPIC_H__ */ |
| 85 | #endif /* __KERNEL__ */ | 91 | #endif /* __KERNEL__ */ |
