aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc/kernel/pcic.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc/kernel/pcic.c')
-rw-r--r--arch/sparc/kernel/pcic.c91
1 files changed, 59 insertions, 32 deletions
diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c
index d36a8d391ca0..948601a066ff 100644
--- a/arch/sparc/kernel/pcic.c
+++ b/arch/sparc/kernel/pcic.c
@@ -164,6 +164,9 @@ void __iomem *pcic_regs;
164volatile int pcic_speculative; 164volatile int pcic_speculative;
165volatile int pcic_trapped; 165volatile int pcic_trapped;
166 166
167/* forward */
168unsigned int pcic_build_device_irq(struct platform_device *op,
169 unsigned int real_irq);
167 170
168#define CONFIG_CMD(bus, device_fn, where) (0x80000000 | (((unsigned int)bus) << 16) | (((unsigned int)device_fn) << 8) | (where & ~3)) 171#define CONFIG_CMD(bus, device_fn, where) (0x80000000 | (((unsigned int)bus) << 16) | (((unsigned int)device_fn) << 8) | (where & ~3))
169 172
@@ -284,7 +287,7 @@ int __init pcic_probe(void)
284 struct linux_prom_registers regs[PROMREG_MAX]; 287 struct linux_prom_registers regs[PROMREG_MAX];
285 struct linux_pbm_info* pbm; 288 struct linux_pbm_info* pbm;
286 char namebuf[64]; 289 char namebuf[64];
287 int node; 290 phandle node;
288 int err; 291 int err;
289 292
290 if (pcic0_up) { 293 if (pcic0_up) {
@@ -440,7 +443,7 @@ static int __devinit pdev_to_pnode(struct linux_pbm_info *pbm,
440{ 443{
441 struct linux_prom_pci_registers regs[PROMREG_MAX]; 444 struct linux_prom_pci_registers regs[PROMREG_MAX];
442 int err; 445 int err;
443 int node = prom_getchild(pbm->prom_node); 446 phandle node = prom_getchild(pbm->prom_node);
444 447
445 while(node) { 448 while(node) {
446 err = prom_getproperty(node, "reg", 449 err = prom_getproperty(node, "reg",
@@ -523,6 +526,7 @@ static void
523pcic_fill_irq(struct linux_pcic *pcic, struct pci_dev *dev, int node) 526pcic_fill_irq(struct linux_pcic *pcic, struct pci_dev *dev, int node)
524{ 527{
525 struct pcic_ca2irq *p; 528 struct pcic_ca2irq *p;
529 unsigned int real_irq;
526 int i, ivec; 530 int i, ivec;
527 char namebuf[64]; 531 char namebuf[64];
528 532
@@ -551,26 +555,25 @@ pcic_fill_irq(struct linux_pcic *pcic, struct pci_dev *dev, int node)
551 i = p->pin; 555 i = p->pin;
552 if (i >= 0 && i < 4) { 556 if (i >= 0 && i < 4) {
553 ivec = readw(pcic->pcic_regs+PCI_INT_SELECT_LO); 557 ivec = readw(pcic->pcic_regs+PCI_INT_SELECT_LO);
554 dev->irq = ivec >> (i << 2) & 0xF; 558 real_irq = ivec >> (i << 2) & 0xF;
555 } else if (i >= 4 && i < 8) { 559 } else if (i >= 4 && i < 8) {
556 ivec = readw(pcic->pcic_regs+PCI_INT_SELECT_HI); 560 ivec = readw(pcic->pcic_regs+PCI_INT_SELECT_HI);
557 dev->irq = ivec >> ((i-4) << 2) & 0xF; 561 real_irq = ivec >> ((i-4) << 2) & 0xF;
558 } else { /* Corrupted map */ 562 } else { /* Corrupted map */
559 printk("PCIC: BAD PIN %d\n", i); for (;;) {} 563 printk("PCIC: BAD PIN %d\n", i); for (;;) {}
560 } 564 }
561/* P3 */ /* printk("PCIC: device %s pin %d ivec 0x%x irq %x\n", namebuf, i, ivec, dev->irq); */ 565/* P3 */ /* printk("PCIC: device %s pin %d ivec 0x%x irq %x\n", namebuf, i, ivec, dev->irq); */
562 566
563 /* 567 /* real_irq means PROM did not bother to program the upper
564 * dev->irq=0 means PROM did not bother to program the upper
565 * half of PCIC. This happens on JS-E with PROM 3.11, for instance. 568 * half of PCIC. This happens on JS-E with PROM 3.11, for instance.
566 */ 569 */
567 if (dev->irq == 0 || p->force) { 570 if (real_irq == 0 || p->force) {
568 if (p->irq == 0 || p->irq >= 15) { /* Corrupted map */ 571 if (p->irq == 0 || p->irq >= 15) { /* Corrupted map */
569 printk("PCIC: BAD IRQ %d\n", p->irq); for (;;) {} 572 printk("PCIC: BAD IRQ %d\n", p->irq); for (;;) {}
570 } 573 }
571 printk("PCIC: setting irq %d at pin %d for device %02x:%02x\n", 574 printk("PCIC: setting irq %d at pin %d for device %02x:%02x\n",
572 p->irq, p->pin, dev->bus->number, dev->devfn); 575 p->irq, p->pin, dev->bus->number, dev->devfn);
573 dev->irq = p->irq; 576 real_irq = p->irq;
574 577
575 i = p->pin; 578 i = p->pin;
576 if (i >= 4) { 579 if (i >= 4) {
@@ -584,7 +587,8 @@ pcic_fill_irq(struct linux_pcic *pcic, struct pci_dev *dev, int node)
584 ivec |= p->irq << (i << 2); 587 ivec |= p->irq << (i << 2);
585 writew(ivec, pcic->pcic_regs+PCI_INT_SELECT_LO); 588 writew(ivec, pcic->pcic_regs+PCI_INT_SELECT_LO);
586 } 589 }
587 } 590 }
591 dev->irq = pcic_build_device_irq(NULL, real_irq);
588} 592}
589 593
590/* 594/*
@@ -700,10 +704,8 @@ static void pcic_clear_clock_irq(void)
700 704
701static irqreturn_t pcic_timer_handler (int irq, void *h) 705static irqreturn_t pcic_timer_handler (int irq, void *h)
702{ 706{
703 write_seqlock(&xtime_lock); /* Dummy, to show that we remember */
704 pcic_clear_clock_irq(); 707 pcic_clear_clock_irq();
705 do_timer(1); 708 xtime_update(1);
706 write_sequnlock(&xtime_lock);
707#ifndef CONFIG_SMP 709#ifndef CONFIG_SMP
708 update_process_times(user_mode(get_irq_regs())); 710 update_process_times(user_mode(get_irq_regs()));
709#endif 711#endif
@@ -731,6 +733,7 @@ void __init pci_time_init(void)
731 struct linux_pcic *pcic = &pcic0; 733 struct linux_pcic *pcic = &pcic0;
732 unsigned long v; 734 unsigned long v;
733 int timer_irq, irq; 735 int timer_irq, irq;
736 int err;
734 737
735 do_arch_gettimeoffset = pci_gettimeoffset; 738 do_arch_gettimeoffset = pci_gettimeoffset;
736 739
@@ -742,9 +745,10 @@ void __init pci_time_init(void)
742 timer_irq = PCI_COUNTER_IRQ_SYS(v); 745 timer_irq = PCI_COUNTER_IRQ_SYS(v);
743 writel (PCI_COUNTER_IRQ_SET(timer_irq, 0), 746 writel (PCI_COUNTER_IRQ_SET(timer_irq, 0),
744 pcic->pcic_regs+PCI_COUNTER_IRQ); 747 pcic->pcic_regs+PCI_COUNTER_IRQ);
745 irq = request_irq(timer_irq, pcic_timer_handler, 748 irq = pcic_build_device_irq(NULL, timer_irq);
746 (IRQF_DISABLED | SA_STATIC_ALLOC), "timer", NULL); 749 err = request_irq(irq, pcic_timer_handler,
747 if (irq) { 750 IRQF_TIMER, "timer", NULL);
751 if (err) {
748 prom_printf("time_init: unable to attach IRQ%d\n", timer_irq); 752 prom_printf("time_init: unable to attach IRQ%d\n", timer_irq);
749 prom_halt(); 753 prom_halt();
750 } 754 }
@@ -805,50 +809,73 @@ static inline unsigned long get_irqmask(int irq_nr)
805 return 1 << irq_nr; 809 return 1 << irq_nr;
806} 810}
807 811
808static void pcic_disable_irq(unsigned int irq_nr) 812static void pcic_mask_irq(struct irq_data *data)
809{ 813{
810 unsigned long mask, flags; 814 unsigned long mask, flags;
811 815
812 mask = get_irqmask(irq_nr); 816 mask = (unsigned long)data->chip_data;
813 local_irq_save(flags); 817 local_irq_save(flags);
814 writel(mask, pcic0.pcic_regs+PCI_SYS_INT_TARGET_MASK_SET); 818 writel(mask, pcic0.pcic_regs+PCI_SYS_INT_TARGET_MASK_SET);
815 local_irq_restore(flags); 819 local_irq_restore(flags);
816} 820}
817 821
818static void pcic_enable_irq(unsigned int irq_nr) 822static void pcic_unmask_irq(struct irq_data *data)
819{ 823{
820 unsigned long mask, flags; 824 unsigned long mask, flags;
821 825
822 mask = get_irqmask(irq_nr); 826 mask = (unsigned long)data->chip_data;
823 local_irq_save(flags); 827 local_irq_save(flags);
824 writel(mask, pcic0.pcic_regs+PCI_SYS_INT_TARGET_MASK_CLEAR); 828 writel(mask, pcic0.pcic_regs+PCI_SYS_INT_TARGET_MASK_CLEAR);
825 local_irq_restore(flags); 829 local_irq_restore(flags);
826} 830}
827 831
828static void pcic_load_profile_irq(int cpu, unsigned int limit) 832static unsigned int pcic_startup_irq(struct irq_data *data)
829{ 833{
830 printk("PCIC: unimplemented code: FILE=%s LINE=%d", __FILE__, __LINE__); 834 irq_link(data->irq);
835 pcic_unmask_irq(data);
836 return 0;
831} 837}
832 838
833/* We assume the caller has disabled local interrupts when these are called, 839static struct irq_chip pcic_irq = {
834 * or else very bizarre behavior will result. 840 .name = "pcic",
835 */ 841 .irq_startup = pcic_startup_irq,
836static void pcic_disable_pil_irq(unsigned int pil) 842 .irq_mask = pcic_mask_irq,
843 .irq_unmask = pcic_unmask_irq,
844};
845
846unsigned int pcic_build_device_irq(struct platform_device *op,
847 unsigned int real_irq)
837{ 848{
838 writel(get_irqmask(pil), pcic0.pcic_regs+PCI_SYS_INT_TARGET_MASK_SET); 849 unsigned int irq;
850 unsigned long mask;
851
852 irq = 0;
853 mask = get_irqmask(real_irq);
854 if (mask == 0)
855 goto out;
856
857 irq = irq_alloc(real_irq, real_irq);
858 if (irq == 0)
859 goto out;
860
861 irq_set_chip_and_handler_name(irq, &pcic_irq,
862 handle_level_irq, "PCIC");
863 irq_set_chip_data(irq, (void *)mask);
864
865out:
866 return irq;
839} 867}
840 868
841static void pcic_enable_pil_irq(unsigned int pil) 869
870static void pcic_load_profile_irq(int cpu, unsigned int limit)
842{ 871{
843 writel(get_irqmask(pil), pcic0.pcic_regs+PCI_SYS_INT_TARGET_MASK_CLEAR); 872 printk("PCIC: unimplemented code: FILE=%s LINE=%d", __FILE__, __LINE__);
844} 873}
845 874
846void __init sun4m_pci_init_IRQ(void) 875void __init sun4m_pci_init_IRQ(void)
847{ 876{
848 BTFIXUPSET_CALL(enable_irq, pcic_enable_irq, BTFIXUPCALL_NORM); 877 sparc_irq_config.build_device_irq = pcic_build_device_irq;
849 BTFIXUPSET_CALL(disable_irq, pcic_disable_irq, BTFIXUPCALL_NORM); 878
850 BTFIXUPSET_CALL(enable_pil_irq, pcic_enable_pil_irq, BTFIXUPCALL_NORM);
851 BTFIXUPSET_CALL(disable_pil_irq, pcic_disable_pil_irq, BTFIXUPCALL_NORM);
852 BTFIXUPSET_CALL(clear_clock_irq, pcic_clear_clock_irq, BTFIXUPCALL_NORM); 879 BTFIXUPSET_CALL(clear_clock_irq, pcic_clear_clock_irq, BTFIXUPCALL_NORM);
853 BTFIXUPSET_CALL(load_profile_irq, pcic_load_profile_irq, BTFIXUPCALL_NORM); 880 BTFIXUPSET_CALL(load_profile_irq, pcic_load_profile_irq, BTFIXUPCALL_NORM);
854} 881}