diff options
Diffstat (limited to 'arch/powerpc/sysdev')
| -rw-r--r-- | arch/powerpc/sysdev/Makefile | 4 | ||||
| -rw-r--r-- | arch/powerpc/sysdev/ipic.c | 303 | ||||
| -rw-r--r-- | arch/powerpc/sysdev/ipic.h | 23 | ||||
| -rw-r--r-- | arch/powerpc/sysdev/mpic.c | 223 |
4 files changed, 394 insertions, 159 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/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c index 46801f5ec03f..70e707785d49 100644 --- a/arch/powerpc/sysdev/ipic.c +++ b/arch/powerpc/sysdev/ipic.c | |||
| @@ -19,15 +19,18 @@ | |||
| 19 | #include <linux/sched.h> | 19 | #include <linux/sched.h> |
| 20 | #include <linux/signal.h> | 20 | #include <linux/signal.h> |
| 21 | #include <linux/sysdev.h> | 21 | #include <linux/sysdev.h> |
| 22 | #include <linux/device.h> | ||
| 23 | #include <linux/bootmem.h> | ||
| 24 | #include <linux/spinlock.h> | ||
| 22 | #include <asm/irq.h> | 25 | #include <asm/irq.h> |
| 23 | #include <asm/io.h> | 26 | #include <asm/io.h> |
| 27 | #include <asm/prom.h> | ||
| 24 | #include <asm/ipic.h> | 28 | #include <asm/ipic.h> |
| 25 | #include <asm/mpc83xx.h> | ||
| 26 | 29 | ||
| 27 | #include "ipic.h" | 30 | #include "ipic.h" |
| 28 | 31 | ||
| 29 | static struct ipic p_ipic; | ||
| 30 | static struct ipic * primary_ipic; | 32 | static struct ipic * primary_ipic; |
| 33 | static DEFINE_SPINLOCK(ipic_lock); | ||
| 31 | 34 | ||
| 32 | static struct ipic_info ipic_info[] = { | 35 | static struct ipic_info ipic_info[] = { |
| 33 | [9] = { | 36 | [9] = { |
| @@ -373,74 +376,220 @@ static inline void ipic_write(volatile u32 __iomem *base, unsigned int reg, u32 | |||
| 373 | out_be32(base + (reg >> 2), value); | 376 | out_be32(base + (reg >> 2), value); |
| 374 | } | 377 | } |
| 375 | 378 | ||
| 376 | static inline struct ipic * ipic_from_irq(unsigned int irq) | 379 | static inline struct ipic * ipic_from_irq(unsigned int virq) |
| 377 | { | 380 | { |
| 378 | return primary_ipic; | 381 | return primary_ipic; |
| 379 | } | 382 | } |
| 380 | 383 | ||
| 381 | static void ipic_enable_irq(unsigned int irq) | 384 | #define ipic_irq_to_hw(virq) ((unsigned int)irq_map[virq].hwirq) |
| 385 | |||
| 386 | static void ipic_unmask_irq(unsigned int virq) | ||
| 382 | { | 387 | { |
| 383 | struct ipic *ipic = ipic_from_irq(irq); | 388 | struct ipic *ipic = ipic_from_irq(virq); |
| 384 | unsigned int src = irq - ipic->irq_offset; | 389 | unsigned int src = ipic_irq_to_hw(virq); |
| 390 | unsigned long flags; | ||
| 385 | u32 temp; | 391 | u32 temp; |
| 386 | 392 | ||
| 393 | spin_lock_irqsave(&ipic_lock, flags); | ||
| 394 | |||
| 387 | temp = ipic_read(ipic->regs, ipic_info[src].mask); | 395 | temp = ipic_read(ipic->regs, ipic_info[src].mask); |
| 388 | temp |= (1 << (31 - ipic_info[src].bit)); | 396 | temp |= (1 << (31 - ipic_info[src].bit)); |
| 389 | ipic_write(ipic->regs, ipic_info[src].mask, temp); | 397 | ipic_write(ipic->regs, ipic_info[src].mask, temp); |
| 398 | |||
| 399 | spin_unlock_irqrestore(&ipic_lock, flags); | ||
| 390 | } | 400 | } |
| 391 | 401 | ||
| 392 | static void ipic_disable_irq(unsigned int irq) | 402 | static void ipic_mask_irq(unsigned int virq) |
| 393 | { | 403 | { |
| 394 | struct ipic *ipic = ipic_from_irq(irq); | 404 | struct ipic *ipic = ipic_from_irq(virq); |
| 395 | unsigned int src = irq - ipic->irq_offset; | 405 | unsigned int src = ipic_irq_to_hw(virq); |
| 406 | unsigned long flags; | ||
| 396 | u32 temp; | 407 | u32 temp; |
| 397 | 408 | ||
| 409 | spin_lock_irqsave(&ipic_lock, flags); | ||
| 410 | |||
| 398 | temp = ipic_read(ipic->regs, ipic_info[src].mask); | 411 | temp = ipic_read(ipic->regs, ipic_info[src].mask); |
| 399 | temp &= ~(1 << (31 - ipic_info[src].bit)); | 412 | temp &= ~(1 << (31 - ipic_info[src].bit)); |
| 400 | ipic_write(ipic->regs, ipic_info[src].mask, temp); | 413 | ipic_write(ipic->regs, ipic_info[src].mask, temp); |
| 414 | |||
| 415 | spin_unlock_irqrestore(&ipic_lock, flags); | ||
| 401 | } | 416 | } |
| 402 | 417 | ||
| 403 | static void ipic_disable_irq_and_ack(unsigned int irq) | 418 | static void ipic_ack_irq(unsigned int virq) |
| 404 | { | 419 | { |
| 405 | struct ipic *ipic = ipic_from_irq(irq); | 420 | struct ipic *ipic = ipic_from_irq(virq); |
| 406 | unsigned int src = irq - ipic->irq_offset; | 421 | unsigned int src = ipic_irq_to_hw(virq); |
| 422 | unsigned long flags; | ||
| 407 | u32 temp; | 423 | u32 temp; |
| 408 | 424 | ||
| 409 | ipic_disable_irq(irq); | 425 | spin_lock_irqsave(&ipic_lock, flags); |
| 410 | 426 | ||
| 411 | temp = ipic_read(ipic->regs, ipic_info[src].pend); | 427 | temp = ipic_read(ipic->regs, ipic_info[src].pend); |
| 412 | temp |= (1 << (31 - ipic_info[src].bit)); | 428 | temp |= (1 << (31 - ipic_info[src].bit)); |
| 413 | ipic_write(ipic->regs, ipic_info[src].pend, temp); | 429 | ipic_write(ipic->regs, ipic_info[src].pend, temp); |
| 430 | |||
| 431 | spin_unlock_irqrestore(&ipic_lock, flags); | ||
| 414 | } | 432 | } |
| 415 | 433 | ||
| 416 | static void ipic_end_irq(unsigned int irq) | 434 | static void ipic_mask_irq_and_ack(unsigned int virq) |
| 417 | { | 435 | { |
| 418 | if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) | 436 | struct ipic *ipic = ipic_from_irq(virq); |
| 419 | ipic_enable_irq(irq); | 437 | unsigned int src = ipic_irq_to_hw(virq); |
| 438 | unsigned long flags; | ||
| 439 | u32 temp; | ||
| 440 | |||
| 441 | spin_lock_irqsave(&ipic_lock, flags); | ||
| 442 | |||
| 443 | temp = ipic_read(ipic->regs, ipic_info[src].mask); | ||
| 444 | temp &= ~(1 << (31 - ipic_info[src].bit)); | ||
| 445 | ipic_write(ipic->regs, ipic_info[src].mask, temp); | ||
| 446 | |||
| 447 | temp = ipic_read(ipic->regs, ipic_info[src].pend); | ||
| 448 | temp |= (1 << (31 - ipic_info[src].bit)); | ||
| 449 | ipic_write(ipic->regs, ipic_info[src].pend, temp); | ||
| 450 | |||
| 451 | spin_unlock_irqrestore(&ipic_lock, flags); | ||
| 420 | } | 452 | } |
| 421 | 453 | ||
| 422 | struct hw_interrupt_type ipic = { | 454 | static int ipic_set_irq_type(unsigned int virq, unsigned int flow_type) |
| 423 | .typename = " IPIC ", | 455 | { |
| 424 | .enable = ipic_enable_irq, | 456 | struct ipic *ipic = ipic_from_irq(virq); |
| 425 | .disable = ipic_disable_irq, | 457 | unsigned int src = ipic_irq_to_hw(virq); |
| 426 | .ack = ipic_disable_irq_and_ack, | 458 | struct irq_desc *desc = get_irq_desc(virq); |
| 427 | .end = ipic_end_irq, | 459 | unsigned int vold, vnew, edibit; |
| 460 | |||
| 461 | if (flow_type == IRQ_TYPE_NONE) | ||
| 462 | flow_type = IRQ_TYPE_LEVEL_LOW; | ||
| 463 | |||
| 464 | /* ipic supports only low assertion and high-to-low change senses | ||
| 465 | */ | ||
| 466 | if (!(flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_EDGE_FALLING))) { | ||
| 467 | printk(KERN_ERR "ipic: sense type 0x%x not supported\n", | ||
| 468 | flow_type); | ||
| 469 | return -EINVAL; | ||
| 470 | } | ||
| 471 | |||
| 472 | desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL); | ||
| 473 | desc->status |= flow_type & IRQ_TYPE_SENSE_MASK; | ||
| 474 | if (flow_type & IRQ_TYPE_LEVEL_LOW) { | ||
| 475 | desc->status |= IRQ_LEVEL; | ||
| 476 | set_irq_handler(virq, handle_level_irq); | ||
| 477 | } else { | ||
| 478 | set_irq_handler(virq, handle_edge_irq); | ||
| 479 | } | ||
| 480 | |||
| 481 | /* only EXT IRQ senses are programmable on ipic | ||
| 482 | * internal IRQ senses are LEVEL_LOW | ||
| 483 | */ | ||
| 484 | if (src == IPIC_IRQ_EXT0) | ||
| 485 | edibit = 15; | ||
| 486 | else | ||
| 487 | if (src >= IPIC_IRQ_EXT1 && src <= IPIC_IRQ_EXT7) | ||
| 488 | edibit = (14 - (src - IPIC_IRQ_EXT1)); | ||
| 489 | else | ||
| 490 | return (flow_type & IRQ_TYPE_LEVEL_LOW) ? 0 : -EINVAL; | ||
| 491 | |||
| 492 | vold = ipic_read(ipic->regs, IPIC_SECNR); | ||
| 493 | if ((flow_type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_FALLING) { | ||
| 494 | vnew = vold | (1 << edibit); | ||
| 495 | } else { | ||
| 496 | vnew = vold & ~(1 << edibit); | ||
| 497 | } | ||
| 498 | if (vold != vnew) | ||
| 499 | ipic_write(ipic->regs, IPIC_SECNR, vnew); | ||
| 500 | return 0; | ||
| 501 | } | ||
| 502 | |||
| 503 | static struct irq_chip ipic_irq_chip = { | ||
| 504 | .typename = " IPIC ", | ||
| 505 | .unmask = ipic_unmask_irq, | ||
| 506 | .mask = ipic_mask_irq, | ||
| 507 | .mask_ack = ipic_mask_irq_and_ack, | ||
| 508 | .ack = ipic_ack_irq, | ||
| 509 | .set_type = ipic_set_irq_type, | ||
| 510 | }; | ||
| 511 | |||
| 512 | static int ipic_host_match(struct irq_host *h, struct device_node *node) | ||
| 513 | { | ||
| 514 | struct ipic *ipic = h->host_data; | ||
| 515 | |||
| 516 | /* Exact match, unless ipic node is NULL */ | ||
| 517 | return ipic->of_node == NULL || ipic->of_node == node; | ||
| 518 | } | ||
| 519 | |||
| 520 | static int ipic_host_map(struct irq_host *h, unsigned int virq, | ||
| 521 | irq_hw_number_t hw) | ||
| 522 | { | ||
| 523 | struct ipic *ipic = h->host_data; | ||
| 524 | struct irq_chip *chip; | ||
| 525 | |||
| 526 | /* Default chip */ | ||
| 527 | chip = &ipic->hc_irq; | ||
| 528 | |||
| 529 | set_irq_chip_data(virq, ipic); | ||
| 530 | set_irq_chip_and_handler(virq, chip, handle_level_irq); | ||
| 531 | |||
| 532 | /* Set default irq type */ | ||
| 533 | set_irq_type(virq, IRQ_TYPE_NONE); | ||
| 534 | |||
| 535 | return 0; | ||
| 536 | } | ||
| 537 | |||
| 538 | static int ipic_host_xlate(struct irq_host *h, struct device_node *ct, | ||
| 539 | u32 *intspec, unsigned int intsize, | ||
| 540 | irq_hw_number_t *out_hwirq, unsigned int *out_flags) | ||
| 541 | |||
| 542 | { | ||
| 543 | /* interrupt sense values coming from the device tree equal either | ||
| 544 | * LEVEL_LOW (low assertion) or EDGE_FALLING (high-to-low change) | ||
| 545 | */ | ||
| 546 | *out_hwirq = intspec[0]; | ||
| 547 | if (intsize > 1) | ||
| 548 | *out_flags = intspec[1]; | ||
| 549 | else | ||
| 550 | *out_flags = IRQ_TYPE_NONE; | ||
| 551 | return 0; | ||
| 552 | } | ||
| 553 | |||
| 554 | static struct irq_host_ops ipic_host_ops = { | ||
| 555 | .match = ipic_host_match, | ||
| 556 | .map = ipic_host_map, | ||
| 557 | .xlate = ipic_host_xlate, | ||
| 428 | }; | 558 | }; |
| 429 | 559 | ||
| 430 | void __init ipic_init(phys_addr_t phys_addr, | 560 | void __init ipic_init(struct device_node *node, |
| 431 | unsigned int flags, | 561 | unsigned int flags) |
| 432 | unsigned int irq_offset, | ||
| 433 | unsigned char *senses, | ||
| 434 | unsigned int senses_count) | ||
| 435 | { | 562 | { |
| 436 | u32 i, temp = 0; | 563 | struct ipic *ipic; |
| 564 | struct resource res; | ||
| 565 | u32 temp = 0, ret; | ||
| 566 | |||
| 567 | ipic = alloc_bootmem(sizeof(struct ipic)); | ||
| 568 | if (ipic == NULL) | ||
| 569 | return; | ||
| 570 | |||
| 571 | memset(ipic, 0, sizeof(struct ipic)); | ||
| 572 | ipic->of_node = node ? of_node_get(node) : NULL; | ||
| 573 | |||
| 574 | ipic->irqhost = irq_alloc_host(IRQ_HOST_MAP_LINEAR, | ||
| 575 | NR_IPIC_INTS, | ||
| 576 | &ipic_host_ops, 0); | ||
| 577 | if (ipic->irqhost == NULL) { | ||
| 578 | of_node_put(node); | ||
| 579 | return; | ||
| 580 | } | ||
| 581 | |||
| 582 | ret = of_address_to_resource(node, 0, &res); | ||
| 583 | if (ret) | ||
| 584 | return; | ||
| 437 | 585 | ||
| 438 | primary_ipic = &p_ipic; | 586 | ipic->regs = ioremap(res.start, res.end - res.start + 1); |
| 439 | primary_ipic->regs = ioremap(phys_addr, MPC83xx_IPIC_SIZE); | ||
| 440 | 587 | ||
| 441 | primary_ipic->irq_offset = irq_offset; | 588 | ipic->irqhost->host_data = ipic; |
| 589 | ipic->hc_irq = ipic_irq_chip; | ||
| 442 | 590 | ||
| 443 | ipic_write(primary_ipic->regs, IPIC_SICNR, 0x0); | 591 | /* init hw */ |
| 592 | ipic_write(ipic->regs, IPIC_SICNR, 0x0); | ||
| 444 | 593 | ||
| 445 | /* default priority scheme is grouped. If spread mode is required | 594 | /* default priority scheme is grouped. If spread mode is required |
| 446 | * configure SICFR accordingly */ | 595 | * configure SICFR accordingly */ |
| @@ -453,49 +602,35 @@ void __init ipic_init(phys_addr_t phys_addr, | |||
| 453 | if (flags & IPIC_SPREADMODE_MIX_B) | 602 | if (flags & IPIC_SPREADMODE_MIX_B) |
| 454 | temp |= SICFR_MPSB; | 603 | temp |= SICFR_MPSB; |
| 455 | 604 | ||
| 456 | ipic_write(primary_ipic->regs, IPIC_SICNR, temp); | 605 | ipic_write(ipic->regs, IPIC_SICNR, temp); |
| 457 | 606 | ||
| 458 | /* handle MCP route */ | 607 | /* handle MCP route */ |
| 459 | temp = 0; | 608 | temp = 0; |
| 460 | if (flags & IPIC_DISABLE_MCP_OUT) | 609 | if (flags & IPIC_DISABLE_MCP_OUT) |
| 461 | temp = SERCR_MCPR; | 610 | temp = SERCR_MCPR; |
| 462 | ipic_write(primary_ipic->regs, IPIC_SERCR, temp); | 611 | ipic_write(ipic->regs, IPIC_SERCR, temp); |
| 463 | 612 | ||
| 464 | /* handle routing of IRQ0 to MCP */ | 613 | /* handle routing of IRQ0 to MCP */ |
| 465 | temp = ipic_read(primary_ipic->regs, IPIC_SEMSR); | 614 | temp = ipic_read(ipic->regs, IPIC_SEMSR); |
| 466 | 615 | ||
| 467 | if (flags & IPIC_IRQ0_MCP) | 616 | if (flags & IPIC_IRQ0_MCP) |
| 468 | temp |= SEMSR_SIRQ0; | 617 | temp |= SEMSR_SIRQ0; |
| 469 | else | 618 | else |
| 470 | temp &= ~SEMSR_SIRQ0; | 619 | temp &= ~SEMSR_SIRQ0; |
| 471 | 620 | ||
| 472 | ipic_write(primary_ipic->regs, IPIC_SEMSR, temp); | 621 | ipic_write(ipic->regs, IPIC_SEMSR, temp); |
| 473 | 622 | ||
| 474 | for (i = 0 ; i < NR_IPIC_INTS ; i++) { | 623 | primary_ipic = ipic; |
| 475 | irq_desc[i+irq_offset].chip = &ipic; | 624 | irq_set_default_host(primary_ipic->irqhost); |
| 476 | irq_desc[i+irq_offset].status = IRQ_LEVEL; | ||
| 477 | } | ||
| 478 | 625 | ||
| 479 | temp = 0; | 626 | printk ("IPIC (%d IRQ sources) at %p\n", NR_IPIC_INTS, |
| 480 | for (i = 0 ; i < senses_count ; i++) { | 627 | primary_ipic->regs); |
| 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 | } | 628 | } |
| 494 | 629 | ||
| 495 | int ipic_set_priority(unsigned int irq, unsigned int priority) | 630 | int ipic_set_priority(unsigned int virq, unsigned int priority) |
| 496 | { | 631 | { |
| 497 | struct ipic *ipic = ipic_from_irq(irq); | 632 | struct ipic *ipic = ipic_from_irq(virq); |
| 498 | unsigned int src = irq - ipic->irq_offset; | 633 | unsigned int src = ipic_irq_to_hw(virq); |
| 499 | u32 temp; | 634 | u32 temp; |
| 500 | 635 | ||
| 501 | if (priority > 7) | 636 | if (priority > 7) |
| @@ -520,10 +655,10 @@ int ipic_set_priority(unsigned int irq, unsigned int priority) | |||
| 520 | return 0; | 655 | return 0; |
| 521 | } | 656 | } |
| 522 | 657 | ||
| 523 | void ipic_set_highest_priority(unsigned int irq) | 658 | void ipic_set_highest_priority(unsigned int virq) |
| 524 | { | 659 | { |
| 525 | struct ipic *ipic = ipic_from_irq(irq); | 660 | struct ipic *ipic = ipic_from_irq(virq); |
| 526 | unsigned int src = irq - ipic->irq_offset; | 661 | unsigned int src = ipic_irq_to_hw(virq); |
| 527 | u32 temp; | 662 | u32 temp; |
| 528 | 663 | ||
| 529 | temp = ipic_read(ipic->regs, IPIC_SICFR); | 664 | temp = ipic_read(ipic->regs, IPIC_SICFR); |
| @@ -537,37 +672,10 @@ void ipic_set_highest_priority(unsigned int irq) | |||
| 537 | 672 | ||
| 538 | void ipic_set_default_priority(void) | 673 | void ipic_set_default_priority(void) |
| 539 | { | 674 | { |
| 540 | ipic_set_priority(MPC83xx_IRQ_TSEC1_TX, 0); | 675 | ipic_write(primary_ipic->regs, IPIC_SIPRR_A, IPIC_SIPRR_A_DEFAULT); |
| 541 | ipic_set_priority(MPC83xx_IRQ_TSEC1_RX, 1); | 676 | ipic_write(primary_ipic->regs, IPIC_SIPRR_D, IPIC_SIPRR_D_DEFAULT); |
| 542 | ipic_set_priority(MPC83xx_IRQ_TSEC1_ERROR, 2); | 677 | ipic_write(primary_ipic->regs, IPIC_SMPRR_A, IPIC_SMPRR_A_DEFAULT); |
| 543 | ipic_set_priority(MPC83xx_IRQ_TSEC2_TX, 3); | 678 | ipic_write(primary_ipic->regs, IPIC_SMPRR_B, IPIC_SMPRR_B_DEFAULT); |
| 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 | } | 679 | } |
| 572 | 680 | ||
| 573 | void ipic_enable_mcp(enum ipic_mcp_irq mcp_irq) | 681 | void ipic_enable_mcp(enum ipic_mcp_irq mcp_irq) |
| @@ -600,17 +708,20 @@ void ipic_clear_mcp_status(u32 mask) | |||
| 600 | ipic_write(primary_ipic->regs, IPIC_SERMR, mask); | 708 | ipic_write(primary_ipic->regs, IPIC_SERMR, mask); |
| 601 | } | 709 | } |
| 602 | 710 | ||
| 603 | /* Return an interrupt vector or -1 if no interrupt is pending. */ | 711 | /* Return an interrupt vector or NO_IRQ if no interrupt is pending. */ |
| 604 | int ipic_get_irq(struct pt_regs *regs) | 712 | unsigned int ipic_get_irq(struct pt_regs *regs) |
| 605 | { | 713 | { |
| 606 | int irq; | 714 | int irq; |
| 607 | 715 | ||
| 608 | irq = ipic_read(primary_ipic->regs, IPIC_SIVCR) & 0x7f; | 716 | BUG_ON(primary_ipic == NULL); |
| 717 | |||
| 718 | #define IPIC_SIVCR_VECTOR_MASK 0x7f | ||
| 719 | irq = ipic_read(primary_ipic->regs, IPIC_SIVCR) & IPIC_SIVCR_VECTOR_MASK; | ||
| 609 | 720 | ||
| 610 | if (irq == 0) /* 0 --> no irq is pending */ | 721 | if (irq == 0) /* 0 --> no irq is pending */ |
| 611 | irq = -1; | 722 | return NO_IRQ; |
| 612 | 723 | ||
| 613 | return irq; | 724 | return irq_linear_revmap(primary_ipic->irqhost, irq); |
| 614 | } | 725 | } |
| 615 | 726 | ||
| 616 | static struct sysdev_class ipic_sysclass = { | 727 | static struct sysdev_class ipic_sysclass = { |
diff --git a/arch/powerpc/sysdev/ipic.h b/arch/powerpc/sysdev/ipic.h index a60c9d18bb7f..c28e589877eb 100644 --- a/arch/powerpc/sysdev/ipic.h +++ b/arch/powerpc/sysdev/ipic.h | |||
| @@ -15,7 +15,18 @@ | |||
| 15 | 15 | ||
| 16 | #include <asm/ipic.h> | 16 | #include <asm/ipic.h> |
| 17 | 17 | ||
| 18 | #define MPC83xx_IPIC_SIZE (0x00100) | 18 | #define NR_IPIC_INTS 128 |
| 19 | |||
| 20 | /* External IRQS */ | ||
| 21 | #define IPIC_IRQ_EXT0 48 | ||
| 22 | #define IPIC_IRQ_EXT1 17 | ||
| 23 | #define IPIC_IRQ_EXT7 23 | ||
| 24 | |||
| 25 | /* Default Priority Registers */ | ||
| 26 | #define IPIC_SIPRR_A_DEFAULT 0x05309770 | ||
| 27 | #define IPIC_SIPRR_D_DEFAULT 0x05309770 | ||
| 28 | #define IPIC_SMPRR_A_DEFAULT 0x05309770 | ||
| 29 | #define IPIC_SMPRR_B_DEFAULT 0x05309770 | ||
| 19 | 30 | ||
| 20 | /* System Global Interrupt Configuration Register */ | 31 | /* System Global Interrupt Configuration Register */ |
| 21 | #define SICFR_IPSA 0x00010000 | 32 | #define SICFR_IPSA 0x00010000 |
| @@ -31,7 +42,15 @@ | |||
| 31 | 42 | ||
| 32 | struct ipic { | 43 | struct ipic { |
| 33 | volatile u32 __iomem *regs; | 44 | volatile u32 __iomem *regs; |
| 34 | unsigned int irq_offset; | 45 | |
| 46 | /* The remapper for this IPIC */ | ||
| 47 | struct irq_host *irqhost; | ||
| 48 | |||
| 49 | /* The "linux" controller struct */ | ||
| 50 | struct irq_chip hc_irq; | ||
| 51 | |||
| 52 | /* The device node of the interrupt controller */ | ||
| 53 | struct device_node *of_node; | ||
| 35 | }; | 54 | }; |
| 36 | 55 | ||
| 37 | struct ipic_info { | 56 | struct ipic_info { |
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index 6e0281afa6c3..b604926401f5 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c | |||
| @@ -54,6 +54,94 @@ static DEFINE_SPINLOCK(mpic_lock); | |||
| 54 | #endif | 54 | #endif |
| 55 | #endif | 55 | #endif |
| 56 | 56 | ||
| 57 | #ifdef CONFIG_MPIC_WEIRD | ||
| 58 | static u32 mpic_infos[][MPIC_IDX_END] = { | ||
| 59 | [0] = { /* Original OpenPIC compatible MPIC */ | ||
| 60 | MPIC_GREG_BASE, | ||
| 61 | MPIC_GREG_FEATURE_0, | ||
| 62 | MPIC_GREG_GLOBAL_CONF_0, | ||
| 63 | MPIC_GREG_VENDOR_ID, | ||
| 64 | MPIC_GREG_IPI_VECTOR_PRI_0, | ||
| 65 | MPIC_GREG_IPI_STRIDE, | ||
| 66 | MPIC_GREG_SPURIOUS, | ||
| 67 | MPIC_GREG_TIMER_FREQ, | ||
| 68 | |||
| 69 | MPIC_TIMER_BASE, | ||
| 70 | MPIC_TIMER_STRIDE, | ||
| 71 | MPIC_TIMER_CURRENT_CNT, | ||
| 72 | MPIC_TIMER_BASE_CNT, | ||
| 73 | MPIC_TIMER_VECTOR_PRI, | ||
| 74 | MPIC_TIMER_DESTINATION, | ||
| 75 | |||
| 76 | MPIC_CPU_BASE, | ||
| 77 | MPIC_CPU_STRIDE, | ||
| 78 | MPIC_CPU_IPI_DISPATCH_0, | ||
| 79 | MPIC_CPU_IPI_DISPATCH_STRIDE, | ||
| 80 | MPIC_CPU_CURRENT_TASK_PRI, | ||
| 81 | MPIC_CPU_WHOAMI, | ||
| 82 | MPIC_CPU_INTACK, | ||
| 83 | MPIC_CPU_EOI, | ||
| 84 | |||
| 85 | MPIC_IRQ_BASE, | ||
| 86 | MPIC_IRQ_STRIDE, | ||
| 87 | MPIC_IRQ_VECTOR_PRI, | ||
| 88 | MPIC_VECPRI_VECTOR_MASK, | ||
| 89 | MPIC_VECPRI_POLARITY_POSITIVE, | ||
| 90 | MPIC_VECPRI_POLARITY_NEGATIVE, | ||
| 91 | MPIC_VECPRI_SENSE_LEVEL, | ||
| 92 | MPIC_VECPRI_SENSE_EDGE, | ||
| 93 | MPIC_VECPRI_POLARITY_MASK, | ||
| 94 | MPIC_VECPRI_SENSE_MASK, | ||
| 95 | MPIC_IRQ_DESTINATION | ||
| 96 | }, | ||
| 97 | [1] = { /* Tsi108/109 PIC */ | ||
| 98 | TSI108_GREG_BASE, | ||
| 99 | TSI108_GREG_FEATURE_0, | ||
| 100 | TSI108_GREG_GLOBAL_CONF_0, | ||
| 101 | TSI108_GREG_VENDOR_ID, | ||
| 102 | TSI108_GREG_IPI_VECTOR_PRI_0, | ||
| 103 | TSI108_GREG_IPI_STRIDE, | ||
| 104 | TSI108_GREG_SPURIOUS, | ||
| 105 | TSI108_GREG_TIMER_FREQ, | ||
| 106 | |||
| 107 | TSI108_TIMER_BASE, | ||
| 108 | TSI108_TIMER_STRIDE, | ||
| 109 | TSI108_TIMER_CURRENT_CNT, | ||
| 110 | TSI108_TIMER_BASE_CNT, | ||
| 111 | TSI108_TIMER_VECTOR_PRI, | ||
| 112 | TSI108_TIMER_DESTINATION, | ||
| 113 | |||
| 114 | TSI108_CPU_BASE, | ||
| 115 | TSI108_CPU_STRIDE, | ||
| 116 | TSI108_CPU_IPI_DISPATCH_0, | ||
| 117 | TSI108_CPU_IPI_DISPATCH_STRIDE, | ||
| 118 | TSI108_CPU_CURRENT_TASK_PRI, | ||
| 119 | TSI108_CPU_WHOAMI, | ||
| 120 | TSI108_CPU_INTACK, | ||
| 121 | TSI108_CPU_EOI, | ||
| 122 | |||
| 123 | TSI108_IRQ_BASE, | ||
| 124 | TSI108_IRQ_STRIDE, | ||
| 125 | TSI108_IRQ_VECTOR_PRI, | ||
| 126 | TSI108_VECPRI_VECTOR_MASK, | ||
| 127 | TSI108_VECPRI_POLARITY_POSITIVE, | ||
| 128 | TSI108_VECPRI_POLARITY_NEGATIVE, | ||
| 129 | TSI108_VECPRI_SENSE_LEVEL, | ||
| 130 | TSI108_VECPRI_SENSE_EDGE, | ||
| 131 | TSI108_VECPRI_POLARITY_MASK, | ||
| 132 | TSI108_VECPRI_SENSE_MASK, | ||
| 133 | TSI108_IRQ_DESTINATION | ||
| 134 | }, | ||
| 135 | }; | ||
| 136 | |||
| 137 | #define MPIC_INFO(name) mpic->hw_set[MPIC_IDX_##name] | ||
| 138 | |||
| 139 | #else /* CONFIG_MPIC_WEIRD */ | ||
| 140 | |||
| 141 | #define MPIC_INFO(name) MPIC_##name | ||
| 142 | |||
| 143 | #endif /* CONFIG_MPIC_WEIRD */ | ||
| 144 | |||
| 57 | /* | 145 | /* |
| 58 | * Register accessor functions | 146 | * Register accessor functions |
| 59 | */ | 147 | */ |
| @@ -80,7 +168,8 @@ static inline void _mpic_write(unsigned int be, volatile u32 __iomem *base, | |||
| 80 | static inline u32 _mpic_ipi_read(struct mpic *mpic, unsigned int ipi) | 168 | static inline u32 _mpic_ipi_read(struct mpic *mpic, unsigned int ipi) |
| 81 | { | 169 | { |
| 82 | unsigned int be = (mpic->flags & MPIC_BIG_ENDIAN) != 0; | 170 | unsigned int be = (mpic->flags & MPIC_BIG_ENDIAN) != 0; |
| 83 | unsigned int offset = MPIC_GREG_IPI_VECTOR_PRI_0 + (ipi * 0x10); | 171 | unsigned int offset = MPIC_INFO(GREG_IPI_VECTOR_PRI_0) + |
| 172 | (ipi * MPIC_INFO(GREG_IPI_STRIDE)); | ||
| 84 | 173 | ||
| 85 | if (mpic->flags & MPIC_BROKEN_IPI) | 174 | if (mpic->flags & MPIC_BROKEN_IPI) |
| 86 | be = !be; | 175 | be = !be; |
| @@ -89,7 +178,8 @@ static inline u32 _mpic_ipi_read(struct mpic *mpic, unsigned int ipi) | |||
| 89 | 178 | ||
| 90 | static inline void _mpic_ipi_write(struct mpic *mpic, unsigned int ipi, u32 value) | 179 | static inline void _mpic_ipi_write(struct mpic *mpic, unsigned int ipi, u32 value) |
| 91 | { | 180 | { |
| 92 | unsigned int offset = MPIC_GREG_IPI_VECTOR_PRI_0 + (ipi * 0x10); | 181 | unsigned int offset = MPIC_INFO(GREG_IPI_VECTOR_PRI_0) + |
| 182 | (ipi * MPIC_INFO(GREG_IPI_STRIDE)); | ||
| 93 | 183 | ||
| 94 | _mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->gregs, offset, value); | 184 | _mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->gregs, offset, value); |
| 95 | } | 185 | } |
| @@ -120,7 +210,7 @@ static inline u32 _mpic_irq_read(struct mpic *mpic, unsigned int src_no, unsigne | |||
| 120 | unsigned int idx = src_no & mpic->isu_mask; | 210 | unsigned int idx = src_no & mpic->isu_mask; |
| 121 | 211 | ||
| 122 | return _mpic_read(mpic->flags & MPIC_BIG_ENDIAN, mpic->isus[isu], | 212 | return _mpic_read(mpic->flags & MPIC_BIG_ENDIAN, mpic->isus[isu], |
| 123 | reg + (idx * MPIC_IRQ_STRIDE)); | 213 | reg + (idx * MPIC_INFO(IRQ_STRIDE))); |
| 124 | } | 214 | } |
| 125 | 215 | ||
| 126 | static inline void _mpic_irq_write(struct mpic *mpic, unsigned int src_no, | 216 | static inline void _mpic_irq_write(struct mpic *mpic, unsigned int src_no, |
| @@ -130,7 +220,7 @@ static inline void _mpic_irq_write(struct mpic *mpic, unsigned int src_no, | |||
| 130 | unsigned int idx = src_no & mpic->isu_mask; | 220 | unsigned int idx = src_no & mpic->isu_mask; |
| 131 | 221 | ||
| 132 | _mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->isus[isu], | 222 | _mpic_write(mpic->flags & MPIC_BIG_ENDIAN, mpic->isus[isu], |
| 133 | reg + (idx * MPIC_IRQ_STRIDE), value); | 223 | reg + (idx * MPIC_INFO(IRQ_STRIDE)), value); |
| 134 | } | 224 | } |
| 135 | 225 | ||
| 136 | #define mpic_read(b,r) _mpic_read(mpic->flags & MPIC_BIG_ENDIAN,(b),(r)) | 226 | #define mpic_read(b,r) _mpic_read(mpic->flags & MPIC_BIG_ENDIAN,(b),(r)) |
| @@ -156,8 +246,8 @@ static void __init mpic_test_broken_ipi(struct mpic *mpic) | |||
| 156 | { | 246 | { |
| 157 | u32 r; | 247 | u32 r; |
| 158 | 248 | ||
| 159 | mpic_write(mpic->gregs, MPIC_GREG_IPI_VECTOR_PRI_0, MPIC_VECPRI_MASK); | 249 | mpic_write(mpic->gregs, MPIC_INFO(GREG_IPI_VECTOR_PRI_0), MPIC_VECPRI_MASK); |
| 160 | r = mpic_read(mpic->gregs, MPIC_GREG_IPI_VECTOR_PRI_0); | 250 | r = mpic_read(mpic->gregs, MPIC_INFO(GREG_IPI_VECTOR_PRI_0)); |
| 161 | 251 | ||
| 162 | if (r == le32_to_cpu(MPIC_VECPRI_MASK)) { | 252 | if (r == le32_to_cpu(MPIC_VECPRI_MASK)) { |
| 163 | printk(KERN_INFO "mpic: Detected reversed IPI registers\n"); | 253 | printk(KERN_INFO "mpic: Detected reversed IPI registers\n"); |
| @@ -394,8 +484,8 @@ static inline struct mpic * mpic_from_irq(unsigned int irq) | |||
| 394 | /* Send an EOI */ | 484 | /* Send an EOI */ |
| 395 | static inline void mpic_eoi(struct mpic *mpic) | 485 | static inline void mpic_eoi(struct mpic *mpic) |
| 396 | { | 486 | { |
| 397 | mpic_cpu_write(MPIC_CPU_EOI, 0); | 487 | mpic_cpu_write(MPIC_INFO(CPU_EOI), 0); |
| 398 | (void)mpic_cpu_read(MPIC_CPU_WHOAMI); | 488 | (void)mpic_cpu_read(MPIC_INFO(CPU_WHOAMI)); |
| 399 | } | 489 | } |
| 400 | 490 | ||
| 401 | #ifdef CONFIG_SMP | 491 | #ifdef CONFIG_SMP |
| @@ -419,8 +509,8 @@ static void mpic_unmask_irq(unsigned int irq) | |||
| 419 | 509 | ||
| 420 | DBG("%p: %s: enable_irq: %d (src %d)\n", mpic, mpic->name, irq, src); | 510 | DBG("%p: %s: enable_irq: %d (src %d)\n", mpic, mpic->name, irq, src); |
| 421 | 511 | ||
| 422 | mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI, | 512 | mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI), |
| 423 | mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & | 513 | mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) & |
| 424 | ~MPIC_VECPRI_MASK); | 514 | ~MPIC_VECPRI_MASK); |
| 425 | /* make sure mask gets to controller before we return to user */ | 515 | /* make sure mask gets to controller before we return to user */ |
| 426 | do { | 516 | do { |
| @@ -428,7 +518,7 @@ static void mpic_unmask_irq(unsigned int irq) | |||
| 428 | printk(KERN_ERR "mpic_enable_irq timeout\n"); | 518 | printk(KERN_ERR "mpic_enable_irq timeout\n"); |
| 429 | break; | 519 | break; |
| 430 | } | 520 | } |
| 431 | } while(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK); | 521 | } while(mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) & MPIC_VECPRI_MASK); |
| 432 | } | 522 | } |
| 433 | 523 | ||
| 434 | static void mpic_mask_irq(unsigned int irq) | 524 | static void mpic_mask_irq(unsigned int irq) |
| @@ -439,8 +529,8 @@ static void mpic_mask_irq(unsigned int irq) | |||
| 439 | 529 | ||
| 440 | DBG("%s: disable_irq: %d (src %d)\n", mpic->name, irq, src); | 530 | DBG("%s: disable_irq: %d (src %d)\n", mpic->name, irq, src); |
| 441 | 531 | ||
| 442 | mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI, | 532 | mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI), |
| 443 | mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) | | 533 | mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) | |
| 444 | MPIC_VECPRI_MASK); | 534 | MPIC_VECPRI_MASK); |
| 445 | 535 | ||
| 446 | /* make sure mask gets to controller before we return to user */ | 536 | /* make sure mask gets to controller before we return to user */ |
| @@ -449,7 +539,7 @@ static void mpic_mask_irq(unsigned int irq) | |||
| 449 | printk(KERN_ERR "mpic_enable_irq timeout\n"); | 539 | printk(KERN_ERR "mpic_enable_irq timeout\n"); |
| 450 | break; | 540 | break; |
| 451 | } | 541 | } |
| 452 | } while(!(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK)); | 542 | } while(!(mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) & MPIC_VECPRI_MASK)); |
| 453 | } | 543 | } |
| 454 | 544 | ||
| 455 | static void mpic_end_irq(unsigned int irq) | 545 | static void mpic_end_irq(unsigned int irq) |
| @@ -560,24 +650,28 @@ static void mpic_set_affinity(unsigned int irq, cpumask_t cpumask) | |||
| 560 | 650 | ||
| 561 | cpus_and(tmp, cpumask, cpu_online_map); | 651 | cpus_and(tmp, cpumask, cpu_online_map); |
| 562 | 652 | ||
| 563 | mpic_irq_write(src, MPIC_IRQ_DESTINATION, | 653 | mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION), |
| 564 | mpic_physmask(cpus_addr(tmp)[0])); | 654 | mpic_physmask(cpus_addr(tmp)[0])); |
| 565 | } | 655 | } |
| 566 | 656 | ||
| 567 | static unsigned int mpic_type_to_vecpri(unsigned int type) | 657 | static unsigned int mpic_type_to_vecpri(struct mpic *mpic, unsigned int type) |
| 568 | { | 658 | { |
| 569 | /* Now convert sense value */ | 659 | /* Now convert sense value */ |
| 570 | switch(type & IRQ_TYPE_SENSE_MASK) { | 660 | switch(type & IRQ_TYPE_SENSE_MASK) { |
| 571 | case IRQ_TYPE_EDGE_RISING: | 661 | case IRQ_TYPE_EDGE_RISING: |
| 572 | return MPIC_VECPRI_SENSE_EDGE | MPIC_VECPRI_POLARITY_POSITIVE; | 662 | return MPIC_INFO(VECPRI_SENSE_EDGE) | |
| 663 | MPIC_INFO(VECPRI_POLARITY_POSITIVE); | ||
| 573 | case IRQ_TYPE_EDGE_FALLING: | 664 | case IRQ_TYPE_EDGE_FALLING: |
| 574 | case IRQ_TYPE_EDGE_BOTH: | 665 | case IRQ_TYPE_EDGE_BOTH: |
| 575 | return MPIC_VECPRI_SENSE_EDGE | MPIC_VECPRI_POLARITY_NEGATIVE; | 666 | return MPIC_INFO(VECPRI_SENSE_EDGE) | |
| 667 | MPIC_INFO(VECPRI_POLARITY_NEGATIVE); | ||
| 576 | case IRQ_TYPE_LEVEL_HIGH: | 668 | case IRQ_TYPE_LEVEL_HIGH: |
| 577 | return MPIC_VECPRI_SENSE_LEVEL | MPIC_VECPRI_POLARITY_POSITIVE; | 669 | return MPIC_INFO(VECPRI_SENSE_LEVEL) | |
| 670 | MPIC_INFO(VECPRI_POLARITY_POSITIVE); | ||
| 578 | case IRQ_TYPE_LEVEL_LOW: | 671 | case IRQ_TYPE_LEVEL_LOW: |
| 579 | default: | 672 | default: |
| 580 | return MPIC_VECPRI_SENSE_LEVEL | MPIC_VECPRI_POLARITY_NEGATIVE; | 673 | return MPIC_INFO(VECPRI_SENSE_LEVEL) | |
| 674 | MPIC_INFO(VECPRI_POLARITY_NEGATIVE); | ||
| 581 | } | 675 | } |
| 582 | } | 676 | } |
| 583 | 677 | ||
| @@ -609,13 +703,14 @@ static int mpic_set_irq_type(unsigned int virq, unsigned int flow_type) | |||
| 609 | vecpri = MPIC_VECPRI_POLARITY_POSITIVE | | 703 | vecpri = MPIC_VECPRI_POLARITY_POSITIVE | |
| 610 | MPIC_VECPRI_SENSE_EDGE; | 704 | MPIC_VECPRI_SENSE_EDGE; |
| 611 | else | 705 | else |
| 612 | vecpri = mpic_type_to_vecpri(flow_type); | 706 | vecpri = mpic_type_to_vecpri(mpic, flow_type); |
| 613 | 707 | ||
| 614 | vold = mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI); | 708 | vold = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)); |
| 615 | vnew = vold & ~(MPIC_VECPRI_POLARITY_MASK | MPIC_VECPRI_SENSE_MASK); | 709 | vnew = vold & ~(MPIC_INFO(VECPRI_POLARITY_MASK) | |
| 710 | MPIC_INFO(VECPRI_SENSE_MASK)); | ||
| 616 | vnew |= vecpri; | 711 | vnew |= vecpri; |
| 617 | if (vold != vnew) | 712 | if (vold != vnew) |
| 618 | mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI, vnew); | 713 | mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI), vnew); |
| 619 | 714 | ||
| 620 | return 0; | 715 | return 0; |
| 621 | } | 716 | } |
| @@ -798,17 +893,22 @@ struct mpic * __init mpic_alloc(struct device_node *node, | |||
| 798 | mpic->irq_count = irq_count; | 893 | mpic->irq_count = irq_count; |
| 799 | mpic->num_sources = 0; /* so far */ | 894 | mpic->num_sources = 0; /* so far */ |
| 800 | 895 | ||
| 896 | #ifdef CONFIG_MPIC_WEIRD | ||
| 897 | mpic->hw_set = mpic_infos[MPIC_GET_REGSET(flags)]; | ||
| 898 | #endif | ||
| 899 | |||
| 801 | /* Map the global registers */ | 900 | /* Map the global registers */ |
| 802 | mpic->gregs = ioremap(phys_addr + MPIC_GREG_BASE, 0x1000); | 901 | mpic->gregs = ioremap(phys_addr + MPIC_INFO(GREG_BASE), 0x1000); |
| 803 | mpic->tmregs = mpic->gregs + ((MPIC_TIMER_BASE - MPIC_GREG_BASE) >> 2); | 902 | mpic->tmregs = mpic->gregs + |
| 903 | ((MPIC_INFO(TIMER_BASE) - MPIC_INFO(GREG_BASE)) >> 2); | ||
| 804 | BUG_ON(mpic->gregs == NULL); | 904 | BUG_ON(mpic->gregs == NULL); |
| 805 | 905 | ||
| 806 | /* Reset */ | 906 | /* Reset */ |
| 807 | if (flags & MPIC_WANTS_RESET) { | 907 | if (flags & MPIC_WANTS_RESET) { |
| 808 | mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0, | 908 | mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0), |
| 809 | mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0) | 909 | mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0)) |
| 810 | | MPIC_GREG_GCONF_RESET); | 910 | | MPIC_GREG_GCONF_RESET); |
| 811 | while( mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0) | 911 | while( mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0)) |
| 812 | & MPIC_GREG_GCONF_RESET) | 912 | & MPIC_GREG_GCONF_RESET) |
| 813 | mb(); | 913 | mb(); |
| 814 | } | 914 | } |
| @@ -817,7 +917,7 @@ struct mpic * __init mpic_alloc(struct device_node *node, | |||
| 817 | * MPICs, num sources as well. On ISU MPICs, sources are counted | 917 | * MPICs, num sources as well. On ISU MPICs, sources are counted |
| 818 | * as ISUs are added | 918 | * as ISUs are added |
| 819 | */ | 919 | */ |
| 820 | reg = mpic_read(mpic->gregs, MPIC_GREG_FEATURE_0); | 920 | reg = mpic_read(mpic->gregs, MPIC_INFO(GREG_FEATURE_0)); |
| 821 | mpic->num_cpus = ((reg & MPIC_GREG_FEATURE_LAST_CPU_MASK) | 921 | mpic->num_cpus = ((reg & MPIC_GREG_FEATURE_LAST_CPU_MASK) |
| 822 | >> MPIC_GREG_FEATURE_LAST_CPU_SHIFT) + 1; | 922 | >> MPIC_GREG_FEATURE_LAST_CPU_SHIFT) + 1; |
| 823 | if (isu_size == 0) | 923 | if (isu_size == 0) |
| @@ -826,16 +926,16 @@ struct mpic * __init mpic_alloc(struct device_node *node, | |||
| 826 | 926 | ||
| 827 | /* Map the per-CPU registers */ | 927 | /* Map the per-CPU registers */ |
| 828 | for (i = 0; i < mpic->num_cpus; i++) { | 928 | for (i = 0; i < mpic->num_cpus; i++) { |
| 829 | mpic->cpuregs[i] = ioremap(phys_addr + MPIC_CPU_BASE + | 929 | mpic->cpuregs[i] = ioremap(phys_addr + MPIC_INFO(CPU_BASE) + |
| 830 | i * MPIC_CPU_STRIDE, 0x1000); | 930 | i * MPIC_INFO(CPU_STRIDE), 0x1000); |
| 831 | BUG_ON(mpic->cpuregs[i] == NULL); | 931 | BUG_ON(mpic->cpuregs[i] == NULL); |
| 832 | } | 932 | } |
| 833 | 933 | ||
| 834 | /* Initialize main ISU if none provided */ | 934 | /* Initialize main ISU if none provided */ |
| 835 | if (mpic->isu_size == 0) { | 935 | if (mpic->isu_size == 0) { |
| 836 | mpic->isu_size = mpic->num_sources; | 936 | mpic->isu_size = mpic->num_sources; |
| 837 | mpic->isus[0] = ioremap(phys_addr + MPIC_IRQ_BASE, | 937 | mpic->isus[0] = ioremap(phys_addr + MPIC_INFO(IRQ_BASE), |
| 838 | MPIC_IRQ_STRIDE * mpic->isu_size); | 938 | MPIC_INFO(IRQ_STRIDE) * mpic->isu_size); |
| 839 | BUG_ON(mpic->isus[0] == NULL); | 939 | BUG_ON(mpic->isus[0] == NULL); |
| 840 | } | 940 | } |
| 841 | mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1); | 941 | mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1); |
| @@ -879,7 +979,8 @@ void __init mpic_assign_isu(struct mpic *mpic, unsigned int isu_num, | |||
| 879 | 979 | ||
| 880 | BUG_ON(isu_num >= MPIC_MAX_ISU); | 980 | BUG_ON(isu_num >= MPIC_MAX_ISU); |
| 881 | 981 | ||
| 882 | mpic->isus[isu_num] = ioremap(phys_addr, MPIC_IRQ_STRIDE * mpic->isu_size); | 982 | mpic->isus[isu_num] = ioremap(phys_addr, |
| 983 | MPIC_INFO(IRQ_STRIDE) * mpic->isu_size); | ||
| 883 | if ((isu_first + mpic->isu_size) > mpic->num_sources) | 984 | if ((isu_first + mpic->isu_size) > mpic->num_sources) |
| 884 | mpic->num_sources = isu_first + mpic->isu_size; | 985 | mpic->num_sources = isu_first + mpic->isu_size; |
| 885 | } | 986 | } |
| @@ -904,14 +1005,16 @@ void __init mpic_init(struct mpic *mpic) | |||
| 904 | printk(KERN_INFO "mpic: Initializing for %d sources\n", mpic->num_sources); | 1005 | printk(KERN_INFO "mpic: Initializing for %d sources\n", mpic->num_sources); |
| 905 | 1006 | ||
| 906 | /* Set current processor priority to max */ | 1007 | /* Set current processor priority to max */ |
| 907 | mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0xf); | 1008 | mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0xf); |
| 908 | 1009 | ||
| 909 | /* Initialize timers: just disable them all */ | 1010 | /* Initialize timers: just disable them all */ |
| 910 | for (i = 0; i < 4; i++) { | 1011 | for (i = 0; i < 4; i++) { |
| 911 | mpic_write(mpic->tmregs, | 1012 | mpic_write(mpic->tmregs, |
| 912 | i * MPIC_TIMER_STRIDE + MPIC_TIMER_DESTINATION, 0); | 1013 | i * MPIC_INFO(TIMER_STRIDE) + |
| 1014 | MPIC_INFO(TIMER_DESTINATION), 0); | ||
| 913 | mpic_write(mpic->tmregs, | 1015 | mpic_write(mpic->tmregs, |
| 914 | i * MPIC_TIMER_STRIDE + MPIC_TIMER_VECTOR_PRI, | 1016 | i * MPIC_INFO(TIMER_STRIDE) + |
| 1017 | MPIC_INFO(TIMER_VECTOR_PRI), | ||
| 915 | MPIC_VECPRI_MASK | | 1018 | MPIC_VECPRI_MASK | |
| 916 | (MPIC_VEC_TIMER_0 + i)); | 1019 | (MPIC_VEC_TIMER_0 + i)); |
| 917 | } | 1020 | } |
| @@ -940,21 +1043,22 @@ void __init mpic_init(struct mpic *mpic) | |||
| 940 | (8 << MPIC_VECPRI_PRIORITY_SHIFT); | 1043 | (8 << MPIC_VECPRI_PRIORITY_SHIFT); |
| 941 | 1044 | ||
| 942 | /* init hw */ | 1045 | /* init hw */ |
| 943 | mpic_irq_write(i, MPIC_IRQ_VECTOR_PRI, vecpri); | 1046 | mpic_irq_write(i, MPIC_INFO(IRQ_VECTOR_PRI), vecpri); |
| 944 | mpic_irq_write(i, MPIC_IRQ_DESTINATION, | 1047 | mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION), |
| 945 | 1 << hard_smp_processor_id()); | 1048 | 1 << hard_smp_processor_id()); |
| 946 | } | 1049 | } |
| 947 | 1050 | ||
| 948 | /* Init spurrious vector */ | 1051 | /* Init spurrious vector */ |
| 949 | mpic_write(mpic->gregs, MPIC_GREG_SPURIOUS, MPIC_VEC_SPURRIOUS); | 1052 | mpic_write(mpic->gregs, MPIC_INFO(GREG_SPURIOUS), MPIC_VEC_SPURRIOUS); |
| 950 | 1053 | ||
| 951 | /* Disable 8259 passthrough */ | 1054 | /* Disable 8259 passthrough, if supported */ |
| 952 | mpic_write(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0, | 1055 | if (!(mpic->flags & MPIC_NO_PTHROU_DIS)) |
| 953 | mpic_read(mpic->gregs, MPIC_GREG_GLOBAL_CONF_0) | 1056 | mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0), |
| 954 | | MPIC_GREG_GCONF_8259_PTHROU_DIS); | 1057 | mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0)) |
| 1058 | | MPIC_GREG_GCONF_8259_PTHROU_DIS); | ||
| 955 | 1059 | ||
| 956 | /* Set current processor priority to 0 */ | 1060 | /* Set current processor priority to 0 */ |
| 957 | mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0); | 1061 | mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0); |
| 958 | } | 1062 | } |
| 959 | 1063 | ||
| 960 | void __init mpic_set_clk_ratio(struct mpic *mpic, u32 clock_ratio) | 1064 | void __init mpic_set_clk_ratio(struct mpic *mpic, u32 clock_ratio) |
| @@ -997,9 +1101,9 @@ void mpic_irq_set_priority(unsigned int irq, unsigned int pri) | |||
| 997 | mpic_ipi_write(src - MPIC_VEC_IPI_0, | 1101 | mpic_ipi_write(src - MPIC_VEC_IPI_0, |
| 998 | reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT)); | 1102 | reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT)); |
| 999 | } else { | 1103 | } else { |
| 1000 | reg = mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) | 1104 | reg = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) |
| 1001 | & ~MPIC_VECPRI_PRIORITY_MASK; | 1105 | & ~MPIC_VECPRI_PRIORITY_MASK; |
| 1002 | mpic_irq_write(src, MPIC_IRQ_VECTOR_PRI, | 1106 | mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI), |
| 1003 | reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT)); | 1107 | reg | (pri << MPIC_VECPRI_PRIORITY_SHIFT)); |
| 1004 | } | 1108 | } |
| 1005 | spin_unlock_irqrestore(&mpic_lock, flags); | 1109 | spin_unlock_irqrestore(&mpic_lock, flags); |
| @@ -1017,7 +1121,7 @@ unsigned int mpic_irq_get_priority(unsigned int irq) | |||
| 1017 | if (is_ipi) | 1121 | if (is_ipi) |
| 1018 | reg = mpic_ipi_read(src = MPIC_VEC_IPI_0); | 1122 | reg = mpic_ipi_read(src = MPIC_VEC_IPI_0); |
| 1019 | else | 1123 | else |
| 1020 | reg = mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI); | 1124 | reg = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)); |
| 1021 | spin_unlock_irqrestore(&mpic_lock, flags); | 1125 | spin_unlock_irqrestore(&mpic_lock, flags); |
| 1022 | return (reg & MPIC_VECPRI_PRIORITY_MASK) >> MPIC_VECPRI_PRIORITY_SHIFT; | 1126 | return (reg & MPIC_VECPRI_PRIORITY_MASK) >> MPIC_VECPRI_PRIORITY_SHIFT; |
| 1023 | } | 1127 | } |
| @@ -1043,12 +1147,12 @@ void mpic_setup_this_cpu(void) | |||
| 1043 | */ | 1147 | */ |
| 1044 | if (distribute_irqs) { | 1148 | if (distribute_irqs) { |
| 1045 | for (i = 0; i < mpic->num_sources ; i++) | 1149 | for (i = 0; i < mpic->num_sources ; i++) |
| 1046 | mpic_irq_write(i, MPIC_IRQ_DESTINATION, | 1150 | mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION), |
| 1047 | mpic_irq_read(i, MPIC_IRQ_DESTINATION) | msk); | 1151 | mpic_irq_read(i, MPIC_INFO(IRQ_DESTINATION)) | msk); |
| 1048 | } | 1152 | } |
| 1049 | 1153 | ||
| 1050 | /* Set current processor priority to 0 */ | 1154 | /* Set current processor priority to 0 */ |
| 1051 | mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0); | 1155 | mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0); |
| 1052 | 1156 | ||
| 1053 | spin_unlock_irqrestore(&mpic_lock, flags); | 1157 | spin_unlock_irqrestore(&mpic_lock, flags); |
| 1054 | #endif /* CONFIG_SMP */ | 1158 | #endif /* CONFIG_SMP */ |
| @@ -1058,7 +1162,7 @@ int mpic_cpu_get_priority(void) | |||
| 1058 | { | 1162 | { |
| 1059 | struct mpic *mpic = mpic_primary; | 1163 | struct mpic *mpic = mpic_primary; |
| 1060 | 1164 | ||
| 1061 | return mpic_cpu_read(MPIC_CPU_CURRENT_TASK_PRI); | 1165 | return mpic_cpu_read(MPIC_INFO(CPU_CURRENT_TASK_PRI)); |
| 1062 | } | 1166 | } |
| 1063 | 1167 | ||
| 1064 | void mpic_cpu_set_priority(int prio) | 1168 | void mpic_cpu_set_priority(int prio) |
| @@ -1066,7 +1170,7 @@ void mpic_cpu_set_priority(int prio) | |||
| 1066 | struct mpic *mpic = mpic_primary; | 1170 | struct mpic *mpic = mpic_primary; |
| 1067 | 1171 | ||
| 1068 | prio &= MPIC_CPU_TASKPRI_MASK; | 1172 | prio &= MPIC_CPU_TASKPRI_MASK; |
| 1069 | mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, prio); | 1173 | mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), prio); |
| 1070 | } | 1174 | } |
| 1071 | 1175 | ||
| 1072 | /* | 1176 | /* |
| @@ -1088,11 +1192,11 @@ void mpic_teardown_this_cpu(int secondary) | |||
| 1088 | 1192 | ||
| 1089 | /* let the mpic know we don't want intrs. */ | 1193 | /* let the mpic know we don't want intrs. */ |
| 1090 | for (i = 0; i < mpic->num_sources ; i++) | 1194 | for (i = 0; i < mpic->num_sources ; i++) |
| 1091 | mpic_irq_write(i, MPIC_IRQ_DESTINATION, | 1195 | mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION), |
| 1092 | mpic_irq_read(i, MPIC_IRQ_DESTINATION) & ~msk); | 1196 | mpic_irq_read(i, MPIC_INFO(IRQ_DESTINATION)) & ~msk); |
| 1093 | 1197 | ||
| 1094 | /* Set current processor priority to max */ | 1198 | /* Set current processor priority to max */ |
| 1095 | mpic_cpu_write(MPIC_CPU_CURRENT_TASK_PRI, 0xf); | 1199 | mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0xf); |
| 1096 | 1200 | ||
| 1097 | spin_unlock_irqrestore(&mpic_lock, flags); | 1201 | spin_unlock_irqrestore(&mpic_lock, flags); |
| 1098 | } | 1202 | } |
| @@ -1108,7 +1212,8 @@ void mpic_send_ipi(unsigned int ipi_no, unsigned int cpu_mask) | |||
| 1108 | DBG("%s: send_ipi(ipi_no: %d)\n", mpic->name, ipi_no); | 1212 | DBG("%s: send_ipi(ipi_no: %d)\n", mpic->name, ipi_no); |
| 1109 | #endif | 1213 | #endif |
| 1110 | 1214 | ||
| 1111 | mpic_cpu_write(MPIC_CPU_IPI_DISPATCH_0 + ipi_no * 0x10, | 1215 | mpic_cpu_write(MPIC_INFO(CPU_IPI_DISPATCH_0) + |
| 1216 | ipi_no * MPIC_INFO(CPU_IPI_DISPATCH_STRIDE), | ||
| 1112 | mpic_physmask(cpu_mask & cpus_addr(cpu_online_map)[0])); | 1217 | mpic_physmask(cpu_mask & cpus_addr(cpu_online_map)[0])); |
| 1113 | } | 1218 | } |
| 1114 | 1219 | ||
| @@ -1116,7 +1221,7 @@ unsigned int mpic_get_one_irq(struct mpic *mpic, struct pt_regs *regs) | |||
| 1116 | { | 1221 | { |
| 1117 | u32 src; | 1222 | u32 src; |
| 1118 | 1223 | ||
| 1119 | src = mpic_cpu_read(MPIC_CPU_INTACK) & MPIC_VECPRI_VECTOR_MASK; | 1224 | src = mpic_cpu_read(MPIC_INFO(CPU_INTACK)) & MPIC_INFO(VECPRI_VECTOR_MASK); |
| 1120 | #ifdef DEBUG_LOW | 1225 | #ifdef DEBUG_LOW |
| 1121 | DBG("%s: get_one_irq(): %d\n", mpic->name, src); | 1226 | DBG("%s: get_one_irq(): %d\n", mpic->name, src); |
| 1122 | #endif | 1227 | #endif |
