aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2005-10-26 02:47:42 -0400
committerPaul Mackerras <paulus@samba.org>2005-10-26 02:47:42 -0400
commitf9bd170a87948a9e077149b70fb192c563770fdf (patch)
treec759b57b67ab41a859e19f7dcee571504b368202 /arch/powerpc
parent25635c71e44111a6bd48f342e144e2fc02d0a314 (diff)
powerpc: Merge i8259.c into arch/powerpc/sysdev
This changes the parameters for i8259_init so that it takes two parameters: a physical address for generating an interrupt acknowledge cycle, and an interrupt number offset. i8259_init now sets the irq_desc[] for its interrupts; all the callers were doing this, and that code is gone now. This also defines a CONFIG_PPC_I8259 symbol to select i8259.o for inclusion, and makes the platforms that need it select that symbol. Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/Kconfig10
-rw-r--r--arch/powerpc/platforms/embedded6xx/Kconfig5
-rw-r--r--arch/powerpc/platforms/pseries/setup.c19
-rw-r--r--arch/powerpc/sysdev/Makefile1
-rw-r--r--arch/powerpc/sysdev/i8259.c221
5 files changed, 241 insertions, 15 deletions
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index a3451d5bb788..9f279e0d84f2 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -275,11 +275,13 @@ endchoice
275config PPC_PSERIES 275config PPC_PSERIES
276 depends on PPC_MULTIPLATFORM && PPC64 276 depends on PPC_MULTIPLATFORM && PPC64
277 bool " IBM pSeries & new (POWER5-based) iSeries" 277 bool " IBM pSeries & new (POWER5-based) iSeries"
278 select PPC_I8259
278 default y 279 default y
279 280
280config PPC_CHRP 281config PPC_CHRP
281 bool " Common Hardware Reference Platform (CHRP) based machines" 282 bool " Common Hardware Reference Platform (CHRP) based machines"
282 depends on PPC_MULTIPLATFORM && PPC32 283 depends on PPC_MULTIPLATFORM && PPC32
284 select PPC_I8259
283 select PPC_INDIRECT_PCI 285 select PPC_INDIRECT_PCI
284 default y 286 default y
285 287
@@ -298,6 +300,7 @@ config PPC_PMAC64
298config PPC_PREP 300config PPC_PREP
299 bool " PowerPC Reference Platform (PReP) based machines" 301 bool " PowerPC Reference Platform (PReP) based machines"
300 depends on PPC_MULTIPLATFORM && PPC32 302 depends on PPC_MULTIPLATFORM && PPC32
303 select PPC_I8259
301 select PPC_INDIRECT_PCI 304 select PPC_INDIRECT_PCI
302 default y 305 default y
303 306
@@ -628,6 +631,7 @@ menu "Bus options"
628config ISA 631config ISA
629 bool "Support for ISA-bus hardware" 632 bool "Support for ISA-bus hardware"
630 depends on PPC_PREP || PPC_CHRP 633 depends on PPC_PREP || PPC_CHRP
634 select PPC_I8259
631 help 635 help
632 Find out whether you have ISA slots on your motherboard. ISA is the 636 Find out whether you have ISA slots on your motherboard. ISA is the
633 name of a bus system, i.e. the way the CPU talks to the other stuff 637 name of a bus system, i.e. the way the CPU talks to the other stuff
@@ -640,6 +644,11 @@ config GENERIC_ISA_DMA
640 depends on PPC64 || POWER4 || 6xx && !CPM2 644 depends on PPC64 || POWER4 || 6xx && !CPM2
641 default y 645 default y
642 646
647config PPC_I8259
648 bool
649 default y if 85xx
650 default n
651
643config PPC_INDIRECT_PCI 652config PPC_INDIRECT_PCI
644 bool 653 bool
645 depends on PCI 654 depends on PCI
@@ -679,6 +688,7 @@ config MPC83xx_PCI2
679config PCI_QSPAN 688config PCI_QSPAN
680 bool "QSpan PCI" 689 bool "QSpan PCI"
681 depends on !4xx && !CPM2 && 8xx 690 depends on !4xx && !CPM2 && 8xx
691 select PPC_I8259
682 help 692 help
683 Say Y here if you have a system based on a Motorola 8xx-series 693 Say Y here if you have a system based on a Motorola 8xx-series
684 embedded processor with a QSPAN PCI interface, otherwise say N. 694 embedded processor with a QSPAN PCI interface, otherwise say N.
diff --git a/arch/powerpc/platforms/embedded6xx/Kconfig b/arch/powerpc/platforms/embedded6xx/Kconfig
index 784b41e19465..81250090f98d 100644
--- a/arch/powerpc/platforms/embedded6xx/Kconfig
+++ b/arch/powerpc/platforms/embedded6xx/Kconfig
@@ -48,6 +48,7 @@ config EV64260
48 48
49config LOPEC 49config LOPEC
50 bool "Motorola-LoPEC" 50 bool "Motorola-LoPEC"
51 select PPC_I8259
51 52
52config MVME5100 53config MVME5100
53 bool "Motorola-MVME5100" 54 bool "Motorola-MVME5100"
@@ -55,6 +56,7 @@ config MVME5100
55 56
56config PPLUS 57config PPLUS
57 bool "Motorola-PowerPlus" 58 bool "Motorola-PowerPlus"
59 select PPC_I8259
58 select PPC_INDIRECT_PCI 60 select PPC_INDIRECT_PCI
59 61
60config PRPMC750 62config PRPMC750
@@ -67,12 +69,14 @@ config PRPMC800
67 69
68config SANDPOINT 70config SANDPOINT
69 bool "Motorola-Sandpoint" 71 bool "Motorola-Sandpoint"
72 select PPC_I8259
70 help 73 help
71 Select SANDPOINT if configuring for a Motorola Sandpoint X3 74 Select SANDPOINT if configuring for a Motorola Sandpoint X3
72 (any flavor). 75 (any flavor).
73 76
74config RADSTONE_PPC7D 77config RADSTONE_PPC7D
75 bool "Radstone Technology PPC7D board" 78 bool "Radstone Technology PPC7D board"
79 select PPC_I8259
76 80
77config PAL4 81config PAL4
78 bool "SBS-Palomar4" 82 bool "SBS-Palomar4"
@@ -307,6 +311,7 @@ config HARRIER_STORE_GATHERING
307config MVME5100_IPMC761_PRESENT 311config MVME5100_IPMC761_PRESENT
308 bool "MVME5100 configured with an IPMC761" 312 bool "MVME5100 configured with an IPMC761"
309 depends on MVME5100 313 depends on MVME5100
314 select PPC_I8259
310 315
311config SPRUCE_BAUD_33M 316config SPRUCE_BAUD_33M
312 bool "Spruce baud clock support" 317 bool "Spruce baud clock support"
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index 92d18003f152..0fa5beae6d1b 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -87,7 +87,6 @@ extern int pSeries_machine_check_exception(struct pt_regs *regs);
87static void pseries_shared_idle(void); 87static void pseries_shared_idle(void);
88static void pseries_dedicated_idle(void); 88static void pseries_dedicated_idle(void);
89 89
90static volatile void __iomem * chrp_int_ack_special;
91struct mpic *pSeries_mpic; 90struct mpic *pSeries_mpic;
92 91
93void pSeries_show_cpuinfo(struct seq_file *m) 92void pSeries_show_cpuinfo(struct seq_file *m)
@@ -119,19 +118,11 @@ static void __init fwnmi_init(void)
119 fwnmi_active = 1; 118 fwnmi_active = 1;
120} 119}
121 120
122static int pSeries_irq_cascade(struct pt_regs *regs, void *data)
123{
124 if (chrp_int_ack_special)
125 return readb(chrp_int_ack_special);
126 else
127 return i8259_irq(regs);
128}
129
130static void __init pSeries_init_mpic(void) 121static void __init pSeries_init_mpic(void)
131{ 122{
132 unsigned int *addrp; 123 unsigned int *addrp;
133 struct device_node *np; 124 struct device_node *np;
134 int i; 125 unsigned long intack = 0;
135 126
136 /* All ISUs are setup, complete initialization */ 127 /* All ISUs are setup, complete initialization */
137 mpic_init(pSeries_mpic); 128 mpic_init(pSeries_mpic);
@@ -142,16 +133,14 @@ static void __init pSeries_init_mpic(void)
142 get_property(np, "8259-interrupt-acknowledge", NULL))) 133 get_property(np, "8259-interrupt-acknowledge", NULL)))
143 printk(KERN_ERR "Cannot find pci to get ack address\n"); 134 printk(KERN_ERR "Cannot find pci to get ack address\n");
144 else 135 else
145 chrp_int_ack_special = ioremap(addrp[prom_n_addr_cells(np)-1], 1); 136 intack = addrp[prom_n_addr_cells(np)-1];
146 of_node_put(np); 137 of_node_put(np);
147 138
148 /* Setup the legacy interrupts & controller */ 139 /* Setup the legacy interrupts & controller */
149 for (i = 0; i < NUM_ISA_INTERRUPTS; i++) 140 i8259_init(intack, 0);
150 irq_desc[i].handler = &i8259_pic;
151 i8259_init(0);
152 141
153 /* Hook cascade to mpic */ 142 /* Hook cascade to mpic */
154 mpic_setup_cascade(NUM_ISA_INTERRUPTS, pSeries_irq_cascade, NULL); 143 mpic_setup_cascade(NUM_ISA_INTERRUPTS, i8259_irq_cascade, NULL);
155} 144}
156 145
157static void __init pSeries_setup_mpic(void) 146static void __init pSeries_setup_mpic(void)
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index e66fef652fac..f3c9e61c3910 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -1,2 +1,3 @@
1obj-$(CONFIG_MPIC) += mpic.o 1obj-$(CONFIG_MPIC) += mpic.o
2obj-$(CONFIG_PPC_INDIRECT_PCI) += indirect_pci.o 2obj-$(CONFIG_PPC_INDIRECT_PCI) += indirect_pci.o
3obj-$(CONFIG_PPC_I8259) += i8259.o
diff --git a/arch/powerpc/sysdev/i8259.c b/arch/powerpc/sysdev/i8259.c
new file mode 100644
index 000000000000..90bce6e0c191
--- /dev/null
+++ b/arch/powerpc/sysdev/i8259.c
@@ -0,0 +1,221 @@
1/*
2 * i8259 interrupt controller driver.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 */
9#include <linux/init.h>
10#include <linux/ioport.h>
11#include <linux/interrupt.h>
12#include <asm/io.h>
13#include <asm/i8259.h>
14
15static volatile void __iomem *pci_intack; /* RO, gives us the irq vector */
16
17static unsigned char cached_8259[2] = { 0xff, 0xff };
18#define cached_A1 (cached_8259[0])
19#define cached_21 (cached_8259[1])
20
21static DEFINE_SPINLOCK(i8259_lock);
22
23static int i8259_pic_irq_offset;
24
25/*
26 * Acknowledge the IRQ using either the PCI host bridge's interrupt
27 * acknowledge feature or poll. How i8259_init() is called determines
28 * which is called. It should be noted that polling is broken on some
29 * IBM and Motorola PReP boxes so we must use the int-ack feature on them.
30 */
31int i8259_irq(struct pt_regs *regs)
32{
33 int irq;
34
35 spin_lock(&i8259_lock);
36
37 /* Either int-ack or poll for the IRQ */
38 if (pci_intack)
39 irq = readb(pci_intack);
40 else {
41 /* Perform an interrupt acknowledge cycle on controller 1. */
42 outb(0x0C, 0x20); /* prepare for poll */
43 irq = inb(0x20) & 7;
44 if (irq == 2 ) {
45 /*
46 * Interrupt is cascaded so perform interrupt
47 * acknowledge on controller 2.
48 */
49 outb(0x0C, 0xA0); /* prepare for poll */
50 irq = (inb(0xA0) & 7) + 8;
51 }
52 }
53
54 if (irq == 7) {
55 /*
56 * This may be a spurious interrupt.
57 *
58 * Read the interrupt status register (ISR). If the most
59 * significant bit is not set then there is no valid
60 * interrupt.
61 */
62 if (!pci_intack)
63 outb(0x0B, 0x20); /* ISR register */
64 if(~inb(0x20) & 0x80)
65 irq = -1;
66 }
67
68 spin_unlock(&i8259_lock);
69 return irq + i8259_pic_irq_offset;
70}
71
72int i8259_irq_cascade(struct pt_regs *regs, void *unused)
73{
74 return i8259_irq(regs);
75}
76
77static void i8259_mask_and_ack_irq(unsigned int irq_nr)
78{
79 unsigned long flags;
80
81 spin_lock_irqsave(&i8259_lock, flags);
82 irq_nr -= i8259_pic_irq_offset;
83 if (irq_nr > 7) {
84 cached_A1 |= 1 << (irq_nr-8);
85 inb(0xA1); /* DUMMY */
86 outb(cached_A1, 0xA1);
87 outb(0x20, 0xA0); /* Non-specific EOI */
88 outb(0x20, 0x20); /* Non-specific EOI to cascade */
89 } else {
90 cached_21 |= 1 << irq_nr;
91 inb(0x21); /* DUMMY */
92 outb(cached_21, 0x21);
93 outb(0x20, 0x20); /* Non-specific EOI */
94 }
95 spin_unlock_irqrestore(&i8259_lock, flags);
96}
97
98static void i8259_set_irq_mask(int irq_nr)
99{
100 outb(cached_A1,0xA1);
101 outb(cached_21,0x21);
102}
103
104static void i8259_mask_irq(unsigned int irq_nr)
105{
106 unsigned long flags;
107
108 spin_lock_irqsave(&i8259_lock, flags);
109 irq_nr -= i8259_pic_irq_offset;
110 if (irq_nr < 8)
111 cached_21 |= 1 << irq_nr;
112 else
113 cached_A1 |= 1 << (irq_nr-8);
114 i8259_set_irq_mask(irq_nr);
115 spin_unlock_irqrestore(&i8259_lock, flags);
116}
117
118static void i8259_unmask_irq(unsigned int irq_nr)
119{
120 unsigned long flags;
121
122 spin_lock_irqsave(&i8259_lock, flags);
123 irq_nr -= i8259_pic_irq_offset;
124 if (irq_nr < 8)
125 cached_21 &= ~(1 << irq_nr);
126 else
127 cached_A1 &= ~(1 << (irq_nr-8));
128 i8259_set_irq_mask(irq_nr);
129 spin_unlock_irqrestore(&i8259_lock, flags);
130}
131
132static void i8259_end_irq(unsigned int irq)
133{
134 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))
135 && irq_desc[irq].action)
136 i8259_unmask_irq(irq);
137}
138
139struct hw_interrupt_type i8259_pic = {
140 .typename = " i8259 ",
141 .enable = i8259_unmask_irq,
142 .disable = i8259_mask_irq,
143 .ack = i8259_mask_and_ack_irq,
144 .end = i8259_end_irq,
145};
146
147static struct resource pic1_iores = {
148 .name = "8259 (master)",
149 .start = 0x20,
150 .end = 0x21,
151 .flags = IORESOURCE_BUSY,
152};
153
154static struct resource pic2_iores = {
155 .name = "8259 (slave)",
156 .start = 0xa0,
157 .end = 0xa1,
158 .flags = IORESOURCE_BUSY,
159};
160
161static struct resource pic_edgectrl_iores = {
162 .name = "8259 edge control",
163 .start = 0x4d0,
164 .end = 0x4d1,
165 .flags = IORESOURCE_BUSY,
166};
167
168static struct irqaction i8259_irqaction = {
169 .handler = no_action,
170 .flags = SA_INTERRUPT,
171 .mask = CPU_MASK_NONE,
172 .name = "82c59 secondary cascade",
173};
174
175/*
176 * i8259_init()
177 * intack_addr - PCI interrupt acknowledge (real) address which will return
178 * the active irq from the 8259
179 */
180void __init i8259_init(unsigned long intack_addr, int offset)
181{
182 unsigned long flags;
183 int i;
184
185 spin_lock_irqsave(&i8259_lock, flags);
186 i8259_pic_irq_offset = offset;
187
188 /* init master interrupt controller */
189 outb(0x11, 0x20); /* Start init sequence */
190 outb(0x00, 0x21); /* Vector base */
191 outb(0x04, 0x21); /* edge tiggered, Cascade (slave) on IRQ2 */
192 outb(0x01, 0x21); /* Select 8086 mode */
193
194 /* init slave interrupt controller */
195 outb(0x11, 0xA0); /* Start init sequence */
196 outb(0x08, 0xA1); /* Vector base */
197 outb(0x02, 0xA1); /* edge triggered, Cascade (slave) on IRQ2 */
198 outb(0x01, 0xA1); /* Select 8086 mode */
199
200 /* always read ISR */
201 outb(0x0B, 0x20);
202 outb(0x0B, 0xA0);
203
204 /* Mask all interrupts */
205 outb(cached_A1, 0xA1);
206 outb(cached_21, 0x21);
207
208 spin_unlock_irqrestore(&i8259_lock, flags);
209
210 /* reserve our resources */
211 setup_irq(offset + 2, &i8259_irqaction);
212 request_resource(&ioport_resource, &pic1_iores);
213 request_resource(&ioport_resource, &pic2_iores);
214 request_resource(&ioport_resource, &pic_edgectrl_iores);
215
216 if (intack_addr != 0)
217 pci_intack = ioremap(intack_addr, 1);
218
219 for (i = 0; i < NUM_ISA_INTERRUPTS; ++i)
220 irq_desc[offset + i].handler = &i8259_pic;
221}