diff options
Diffstat (limited to 'arch/powerpc/sysdev/ipic.c')
-rw-r--r-- | arch/powerpc/sysdev/ipic.c | 112 |
1 files changed, 45 insertions, 67 deletions
diff --git a/arch/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c index d7b9b9c69287..7367d17364cb 100644 --- a/arch/powerpc/sysdev/ipic.c +++ b/arch/powerpc/sysdev/ipic.c | |||
@@ -18,7 +18,7 @@ | |||
18 | #include <linux/stddef.h> | 18 | #include <linux/stddef.h> |
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/syscore_ops.h> |
22 | #include <linux/device.h> | 22 | #include <linux/device.h> |
23 | #include <linux/bootmem.h> | 23 | #include <linux/bootmem.h> |
24 | #include <linux/spinlock.h> | 24 | #include <linux/spinlock.h> |
@@ -521,12 +521,10 @@ static inline struct ipic * ipic_from_irq(unsigned int virq) | |||
521 | return primary_ipic; | 521 | return primary_ipic; |
522 | } | 522 | } |
523 | 523 | ||
524 | #define ipic_irq_to_hw(virq) ((unsigned int)irq_map[virq].hwirq) | 524 | static void ipic_unmask_irq(struct irq_data *d) |
525 | |||
526 | static void ipic_unmask_irq(unsigned int virq) | ||
527 | { | 525 | { |
528 | struct ipic *ipic = ipic_from_irq(virq); | 526 | struct ipic *ipic = ipic_from_irq(d->irq); |
529 | unsigned int src = ipic_irq_to_hw(virq); | 527 | unsigned int src = irqd_to_hwirq(d); |
530 | unsigned long flags; | 528 | unsigned long flags; |
531 | u32 temp; | 529 | u32 temp; |
532 | 530 | ||
@@ -539,10 +537,10 @@ static void ipic_unmask_irq(unsigned int virq) | |||
539 | raw_spin_unlock_irqrestore(&ipic_lock, flags); | 537 | raw_spin_unlock_irqrestore(&ipic_lock, flags); |
540 | } | 538 | } |
541 | 539 | ||
542 | static void ipic_mask_irq(unsigned int virq) | 540 | static void ipic_mask_irq(struct irq_data *d) |
543 | { | 541 | { |
544 | struct ipic *ipic = ipic_from_irq(virq); | 542 | struct ipic *ipic = ipic_from_irq(d->irq); |
545 | unsigned int src = ipic_irq_to_hw(virq); | 543 | unsigned int src = irqd_to_hwirq(d); |
546 | unsigned long flags; | 544 | unsigned long flags; |
547 | u32 temp; | 545 | u32 temp; |
548 | 546 | ||
@@ -559,10 +557,10 @@ static void ipic_mask_irq(unsigned int virq) | |||
559 | raw_spin_unlock_irqrestore(&ipic_lock, flags); | 557 | raw_spin_unlock_irqrestore(&ipic_lock, flags); |
560 | } | 558 | } |
561 | 559 | ||
562 | static void ipic_ack_irq(unsigned int virq) | 560 | static void ipic_ack_irq(struct irq_data *d) |
563 | { | 561 | { |
564 | struct ipic *ipic = ipic_from_irq(virq); | 562 | struct ipic *ipic = ipic_from_irq(d->irq); |
565 | unsigned int src = ipic_irq_to_hw(virq); | 563 | unsigned int src = irqd_to_hwirq(d); |
566 | unsigned long flags; | 564 | unsigned long flags; |
567 | u32 temp; | 565 | u32 temp; |
568 | 566 | ||
@@ -578,10 +576,10 @@ static void ipic_ack_irq(unsigned int virq) | |||
578 | raw_spin_unlock_irqrestore(&ipic_lock, flags); | 576 | raw_spin_unlock_irqrestore(&ipic_lock, flags); |
579 | } | 577 | } |
580 | 578 | ||
581 | static void ipic_mask_irq_and_ack(unsigned int virq) | 579 | static void ipic_mask_irq_and_ack(struct irq_data *d) |
582 | { | 580 | { |
583 | struct ipic *ipic = ipic_from_irq(virq); | 581 | struct ipic *ipic = ipic_from_irq(d->irq); |
584 | unsigned int src = ipic_irq_to_hw(virq); | 582 | unsigned int src = irqd_to_hwirq(d); |
585 | unsigned long flags; | 583 | unsigned long flags; |
586 | u32 temp; | 584 | u32 temp; |
587 | 585 | ||
@@ -601,11 +599,10 @@ static void ipic_mask_irq_and_ack(unsigned int virq) | |||
601 | raw_spin_unlock_irqrestore(&ipic_lock, flags); | 599 | raw_spin_unlock_irqrestore(&ipic_lock, flags); |
602 | } | 600 | } |
603 | 601 | ||
604 | static int ipic_set_irq_type(unsigned int virq, unsigned int flow_type) | 602 | static int ipic_set_irq_type(struct irq_data *d, unsigned int flow_type) |
605 | { | 603 | { |
606 | struct ipic *ipic = ipic_from_irq(virq); | 604 | struct ipic *ipic = ipic_from_irq(d->irq); |
607 | unsigned int src = ipic_irq_to_hw(virq); | 605 | unsigned int src = irqd_to_hwirq(d); |
608 | struct irq_desc *desc = irq_to_desc(virq); | ||
609 | unsigned int vold, vnew, edibit; | 606 | unsigned int vold, vnew, edibit; |
610 | 607 | ||
611 | if (flow_type == IRQ_TYPE_NONE) | 608 | if (flow_type == IRQ_TYPE_NONE) |
@@ -623,17 +620,16 @@ static int ipic_set_irq_type(unsigned int virq, unsigned int flow_type) | |||
623 | printk(KERN_ERR "ipic: edge sense not supported on internal " | 620 | printk(KERN_ERR "ipic: edge sense not supported on internal " |
624 | "interrupts\n"); | 621 | "interrupts\n"); |
625 | return -EINVAL; | 622 | return -EINVAL; |
623 | |||
626 | } | 624 | } |
627 | 625 | ||
628 | desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL); | 626 | irqd_set_trigger_type(d, flow_type); |
629 | desc->status |= flow_type & IRQ_TYPE_SENSE_MASK; | ||
630 | if (flow_type & IRQ_TYPE_LEVEL_LOW) { | 627 | if (flow_type & IRQ_TYPE_LEVEL_LOW) { |
631 | desc->status |= IRQ_LEVEL; | 628 | __irq_set_handler_locked(d->irq, handle_level_irq); |
632 | desc->handle_irq = handle_level_irq; | 629 | d->chip = &ipic_level_irq_chip; |
633 | desc->chip = &ipic_level_irq_chip; | ||
634 | } else { | 630 | } else { |
635 | desc->handle_irq = handle_edge_irq; | 631 | __irq_set_handler_locked(d->irq, handle_edge_irq); |
636 | desc->chip = &ipic_edge_irq_chip; | 632 | d->chip = &ipic_edge_irq_chip; |
637 | } | 633 | } |
638 | 634 | ||
639 | /* only EXT IRQ senses are programmable on ipic | 635 | /* only EXT IRQ senses are programmable on ipic |
@@ -655,25 +651,25 @@ static int ipic_set_irq_type(unsigned int virq, unsigned int flow_type) | |||
655 | } | 651 | } |
656 | if (vold != vnew) | 652 | if (vold != vnew) |
657 | ipic_write(ipic->regs, IPIC_SECNR, vnew); | 653 | ipic_write(ipic->regs, IPIC_SECNR, vnew); |
658 | return 0; | 654 | return IRQ_SET_MASK_OK_NOCOPY; |
659 | } | 655 | } |
660 | 656 | ||
661 | /* level interrupts and edge interrupts have different ack operations */ | 657 | /* level interrupts and edge interrupts have different ack operations */ |
662 | static struct irq_chip ipic_level_irq_chip = { | 658 | static struct irq_chip ipic_level_irq_chip = { |
663 | .name = "IPIC", | 659 | .name = "IPIC", |
664 | .unmask = ipic_unmask_irq, | 660 | .irq_unmask = ipic_unmask_irq, |
665 | .mask = ipic_mask_irq, | 661 | .irq_mask = ipic_mask_irq, |
666 | .mask_ack = ipic_mask_irq, | 662 | .irq_mask_ack = ipic_mask_irq, |
667 | .set_type = ipic_set_irq_type, | 663 | .irq_set_type = ipic_set_irq_type, |
668 | }; | 664 | }; |
669 | 665 | ||
670 | static struct irq_chip ipic_edge_irq_chip = { | 666 | static struct irq_chip ipic_edge_irq_chip = { |
671 | .name = "IPIC", | 667 | .name = "IPIC", |
672 | .unmask = ipic_unmask_irq, | 668 | .irq_unmask = ipic_unmask_irq, |
673 | .mask = ipic_mask_irq, | 669 | .irq_mask = ipic_mask_irq, |
674 | .mask_ack = ipic_mask_irq_and_ack, | 670 | .irq_mask_ack = ipic_mask_irq_and_ack, |
675 | .ack = ipic_ack_irq, | 671 | .irq_ack = ipic_ack_irq, |
676 | .set_type = ipic_set_irq_type, | 672 | .irq_set_type = ipic_set_irq_type, |
677 | }; | 673 | }; |
678 | 674 | ||
679 | static int ipic_host_match(struct irq_host *h, struct device_node *node) | 675 | static int ipic_host_match(struct irq_host *h, struct device_node *node) |
@@ -687,11 +683,11 @@ static int ipic_host_map(struct irq_host *h, unsigned int virq, | |||
687 | { | 683 | { |
688 | struct ipic *ipic = h->host_data; | 684 | struct ipic *ipic = h->host_data; |
689 | 685 | ||
690 | set_irq_chip_data(virq, ipic); | 686 | irq_set_chip_data(virq, ipic); |
691 | set_irq_chip_and_handler(virq, &ipic_level_irq_chip, handle_level_irq); | 687 | irq_set_chip_and_handler(virq, &ipic_level_irq_chip, handle_level_irq); |
692 | 688 | ||
693 | /* Set default irq type */ | 689 | /* Set default irq type */ |
694 | set_irq_type(virq, IRQ_TYPE_NONE); | 690 | irq_set_irq_type(virq, IRQ_TYPE_NONE); |
695 | 691 | ||
696 | return 0; | 692 | return 0; |
697 | } | 693 | } |
@@ -795,7 +791,7 @@ struct ipic * __init ipic_init(struct device_node *node, unsigned int flags) | |||
795 | int ipic_set_priority(unsigned int virq, unsigned int priority) | 791 | int ipic_set_priority(unsigned int virq, unsigned int priority) |
796 | { | 792 | { |
797 | struct ipic *ipic = ipic_from_irq(virq); | 793 | struct ipic *ipic = ipic_from_irq(virq); |
798 | unsigned int src = ipic_irq_to_hw(virq); | 794 | unsigned int src = virq_to_hw(virq); |
799 | u32 temp; | 795 | u32 temp; |
800 | 796 | ||
801 | if (priority > 7) | 797 | if (priority > 7) |
@@ -823,7 +819,7 @@ int ipic_set_priority(unsigned int virq, unsigned int priority) | |||
823 | void ipic_set_highest_priority(unsigned int virq) | 819 | void ipic_set_highest_priority(unsigned int virq) |
824 | { | 820 | { |
825 | struct ipic *ipic = ipic_from_irq(virq); | 821 | struct ipic *ipic = ipic_from_irq(virq); |
826 | unsigned int src = ipic_irq_to_hw(virq); | 822 | unsigned int src = virq_to_hw(virq); |
827 | u32 temp; | 823 | u32 temp; |
828 | 824 | ||
829 | temp = ipic_read(ipic->regs, IPIC_SICFR); | 825 | temp = ipic_read(ipic->regs, IPIC_SICFR); |
@@ -904,7 +900,7 @@ static struct { | |||
904 | u32 sercr; | 900 | u32 sercr; |
905 | } ipic_saved_state; | 901 | } ipic_saved_state; |
906 | 902 | ||
907 | static int ipic_suspend(struct sys_device *sdev, pm_message_t state) | 903 | static int ipic_suspend(void) |
908 | { | 904 | { |
909 | struct ipic *ipic = primary_ipic; | 905 | struct ipic *ipic = primary_ipic; |
910 | 906 | ||
@@ -935,7 +931,7 @@ static int ipic_suspend(struct sys_device *sdev, pm_message_t state) | |||
935 | return 0; | 931 | return 0; |
936 | } | 932 | } |
937 | 933 | ||
938 | static int ipic_resume(struct sys_device *sdev) | 934 | static void ipic_resume(void) |
939 | { | 935 | { |
940 | struct ipic *ipic = primary_ipic; | 936 | struct ipic *ipic = primary_ipic; |
941 | 937 | ||
@@ -951,44 +947,26 @@ static int ipic_resume(struct sys_device *sdev) | |||
951 | ipic_write(ipic->regs, IPIC_SECNR, ipic_saved_state.secnr); | 947 | ipic_write(ipic->regs, IPIC_SECNR, ipic_saved_state.secnr); |
952 | ipic_write(ipic->regs, IPIC_SERMR, ipic_saved_state.sermr); | 948 | ipic_write(ipic->regs, IPIC_SERMR, ipic_saved_state.sermr); |
953 | ipic_write(ipic->regs, IPIC_SERCR, ipic_saved_state.sercr); | 949 | ipic_write(ipic->regs, IPIC_SERCR, ipic_saved_state.sercr); |
954 | |||
955 | return 0; | ||
956 | } | 950 | } |
957 | #else | 951 | #else |
958 | #define ipic_suspend NULL | 952 | #define ipic_suspend NULL |
959 | #define ipic_resume NULL | 953 | #define ipic_resume NULL |
960 | #endif | 954 | #endif |
961 | 955 | ||
962 | static struct sysdev_class ipic_sysclass = { | 956 | static struct syscore_ops ipic_syscore_ops = { |
963 | .name = "ipic", | ||
964 | .suspend = ipic_suspend, | 957 | .suspend = ipic_suspend, |
965 | .resume = ipic_resume, | 958 | .resume = ipic_resume, |
966 | }; | 959 | }; |
967 | 960 | ||
968 | static struct sys_device device_ipic = { | 961 | static int __init init_ipic_syscore(void) |
969 | .id = 0, | ||
970 | .cls = &ipic_sysclass, | ||
971 | }; | ||
972 | |||
973 | static int __init init_ipic_sysfs(void) | ||
974 | { | 962 | { |
975 | int rc; | ||
976 | |||
977 | if (!primary_ipic || !primary_ipic->regs) | 963 | if (!primary_ipic || !primary_ipic->regs) |
978 | return -ENODEV; | 964 | return -ENODEV; |
979 | printk(KERN_DEBUG "Registering ipic with sysfs...\n"); | ||
980 | 965 | ||
981 | rc = sysdev_class_register(&ipic_sysclass); | 966 | printk(KERN_DEBUG "Registering ipic system core operations\n"); |
982 | if (rc) { | 967 | register_syscore_ops(&ipic_syscore_ops); |
983 | printk(KERN_ERR "Failed registering ipic sys class\n"); | 968 | |
984 | return -ENODEV; | ||
985 | } | ||
986 | rc = sysdev_register(&device_ipic); | ||
987 | if (rc) { | ||
988 | printk(KERN_ERR "Failed registering ipic sys device\n"); | ||
989 | return -ENODEV; | ||
990 | } | ||
991 | return 0; | 969 | return 0; |
992 | } | 970 | } |
993 | 971 | ||
994 | subsys_initcall(init_ipic_sysfs); | 972 | subsys_initcall(init_ipic_syscore); |