aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc/kernel/sun4m_irq.c
diff options
context:
space:
mode:
authorSam Ravnborg <sam@ravnborg.org>2011-01-28 17:08:20 -0500
committerDavid S. Miller <davem@davemloft.net>2011-03-16 21:19:09 -0400
commitaba20a8295a76310cd062be0736103ba5aee34fa (patch)
tree391f73a2c6817b3adb018570a8f85a38db4e7585 /arch/sparc/kernel/sun4m_irq.c
parente787098cfe69dad4e7cccf50352e830f539cd50a (diff)
sparc32,sun4m: irq, smp files cleanup
- drop filename in file header - drop unused includes - add description of sun4m interrupts (from davem) - add KERN_* to printk - fix spaces => tabs - add spaces after reserved words - drop all externs, they are now in header files This is partly based on a patch from: David Miller <davem@davemloft.net> Signed-off-by: Sam Ravnborg <sam@ravnborg.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc/kernel/sun4m_irq.c')
-rw-r--r--arch/sparc/kernel/sun4m_irq.c182
1 files changed, 93 insertions, 89 deletions
diff --git a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c
index 7f3b97ff62c1..3c6657a4caec 100644
--- a/arch/sparc/kernel/sun4m_irq.c
+++ b/arch/sparc/kernel/sun4m_irq.c
@@ -1,5 +1,5 @@
1/* sun4m_irq.c 1/*
2 * arch/sparc/kernel/sun4m_irq.c: 2 * sun4m irq support
3 * 3 *
4 * djhr: Hacked out of irq.c into a CPU dependent version. 4 * djhr: Hacked out of irq.c into a CPU dependent version.
5 * 5 *
@@ -9,36 +9,92 @@
9 * Copyright (C) 1996 Dave Redman (djhr@tadpole.co.uk) 9 * Copyright (C) 1996 Dave Redman (djhr@tadpole.co.uk)
10 */ 10 */
11 11
12#include <linux/errno.h>
13#include <linux/linkage.h>
14#include <linux/kernel_stat.h>
15#include <linux/signal.h>
16#include <linux/sched.h>
17#include <linux/ptrace.h>
18#include <linux/smp.h>
19#include <linux/interrupt.h>
20#include <linux/init.h>
21#include <linux/ioport.h>
22#include <linux/of.h>
23#include <linux/of_device.h>
24
25#include <asm/ptrace.h>
26#include <asm/processor.h>
27#include <asm/system.h>
28#include <asm/psr.h>
29#include <asm/vaddrs.h>
30#include <asm/timer.h> 12#include <asm/timer.h>
31#include <asm/openprom.h>
32#include <asm/oplib.h>
33#include <asm/traps.h> 13#include <asm/traps.h>
34#include <asm/pgalloc.h> 14#include <asm/pgalloc.h>
35#include <asm/pgtable.h> 15#include <asm/pgtable.h>
36#include <asm/smp.h>
37#include <asm/irq.h> 16#include <asm/irq.h>
38#include <asm/io.h> 17#include <asm/io.h>
39#include <asm/cacheflush.h> 18#include <asm/cacheflush.h>
40 19
41#include "irq.h" 20#include "irq.h"
21#include "kernel.h"
22
23/* Sample sun4m IRQ layout:
24 *
25 * 0x22 - Power
26 * 0x24 - ESP SCSI
27 * 0x26 - Lance ethernet
28 * 0x2b - Floppy
29 * 0x2c - Zilog uart
30 * 0x32 - SBUS level 0
31 * 0x33 - Parallel port, SBUS level 1
32 * 0x35 - SBUS level 2
33 * 0x37 - SBUS level 3
34 * 0x39 - Audio, Graphics card, SBUS level 4
35 * 0x3b - SBUS level 5
36 * 0x3d - SBUS level 6
37 *
38 * Each interrupt source has a mask bit in the interrupt registers.
39 * When the mask bit is set, this blocks interrupt deliver. So you
40 * clear the bit to enable the interrupt.
41 *
42 * Interrupts numbered less than 0x10 are software triggered interrupts
43 * and unused by Linux.
44 *
45 * Interrupt level assignment on sun4m:
46 *
47 * level source
48 * ------------------------------------------------------------
49 * 1 softint-1
50 * 2 softint-2, VME/SBUS level 1
51 * 3 softint-3, VME/SBUS level 2
52 * 4 softint-4, onboard SCSI
53 * 5 softint-5, VME/SBUS level 3
54 * 6 softint-6, onboard ETHERNET
55 * 7 softint-7, VME/SBUS level 4
56 * 8 softint-8, onboard VIDEO
57 * 9 softint-9, VME/SBUS level 5, Module Interrupt
58 * 10 softint-10, system counter/timer
59 * 11 softint-11, VME/SBUS level 6, Floppy
60 * 12 softint-12, Keyboard/Mouse, Serial
61 * 13 softint-13, VME/SBUS level 7, ISDN Audio
62 * 14 softint-14, per-processor counter/timer
63 * 15 softint-15, Asynchronous Errors (broadcast)
64 *
65 * Each interrupt source is masked distinctly in the sun4m interrupt
66 * registers. The PIL level alone is therefore ambiguous, since multiple
67 * interrupt sources map to a single PIL.
68 *
69 * This ambiguity is resolved in the 'intr' property for device nodes
70 * in the OF device tree. Each 'intr' property entry is composed of
71 * two 32-bit words. The first word is the IRQ priority value, which
72 * is what we're intersted in. The second word is the IRQ vector, which
73 * is unused.
74 *
75 * The low 4 bits of the IRQ priority indicate the PIL, and the upper
76 * 4 bits indicate onboard vs. SBUS leveled vs. VME leveled. 0x20
77 * means onboard, 0x30 means SBUS leveled, and 0x40 means VME leveled.
78 *
79 * For example, an 'intr' IRQ priority value of 0x24 is onboard SCSI
80 * whereas a value of 0x33 is SBUS level 2. Here are some sample
81 * 'intr' property IRQ priority values from ss4, ss5, ss10, ss20, and
82 * Tadpole S3 GX systems.
83 *
84 * esp: 0x24 onboard ESP SCSI
85 * le: 0x26 onboard Lance ETHERNET
86 * p9100: 0x32 SBUS level 1 P9100 video
87 * bpp: 0x33 SBUS level 2 BPP parallel port device
88 * DBRI: 0x39 SBUS level 5 DBRI ISDN audio
89 * SUNW,leo: 0x39 SBUS level 5 LEO video
90 * pcmcia: 0x3b SBUS level 6 PCMCIA controller
91 * uctrl: 0x3b SBUS level 6 UCTRL device
92 * modem: 0x3d SBUS level 7 MODEM
93 * zs: 0x2c onboard keyboard/mouse/serial
94 * floppy: 0x2b onboard Floppy
95 * power: 0x22 onboard power device (XXX unknown mask bit XXX)
96 */
97
42 98
43struct sun4m_irq_percpu { 99struct sun4m_irq_percpu {
44 u32 pending; 100 u32 pending;
@@ -61,9 +117,9 @@ struct sun4m_irq_global __iomem *sun4m_irq_global;
61/* Dave Redman (djhr@tadpole.co.uk) 117/* Dave Redman (djhr@tadpole.co.uk)
62 * The sun4m interrupt registers. 118 * The sun4m interrupt registers.
63 */ 119 */
64#define SUN4M_INT_ENABLE 0x80000000 120#define SUN4M_INT_ENABLE 0x80000000
65#define SUN4M_INT_E14 0x00000080 121#define SUN4M_INT_E14 0x00000080
66#define SUN4M_INT_E10 0x00080000 122#define SUN4M_INT_E10 0x00080000
67 123
68#define SUN4M_HARD_INT(x) (0x000000001 << (x)) 124#define SUN4M_HARD_INT(x) (0x000000001 << (x))
69#define SUN4M_SOFT_INT(x) (0x000010000 << (x)) 125#define SUN4M_SOFT_INT(x) (0x000010000 << (x))
@@ -99,59 +155,6 @@ struct sun4m_irq_global __iomem *sun4m_irq_global;
99#define OBP_INT_LEVEL_SBUS 0x30 155#define OBP_INT_LEVEL_SBUS 0x30
100#define OBP_INT_LEVEL_VME 0x40 156#define OBP_INT_LEVEL_VME 0x40
101 157
102/* Interrupt level assignment on sun4m:
103 *
104 * level source
105 * ------------------------------------------------------------
106 * 1 softint-1
107 * 2 softint-2, VME/SBUS level 1
108 * 3 softint-3, VME/SBUS level 2
109 * 4 softint-4, onboard SCSI
110 * 5 softint-5, VME/SBUS level 3
111 * 6 softint-6, onboard ETHERNET
112 * 7 softint-7, VME/SBUS level 4
113 * 8 softint-8, onboard VIDEO
114 * 9 softint-9, VME/SBUS level 5, Module Interrupt
115 * 10 softint-10, system counter/timer
116 * 11 softint-11, VME/SBUS level 6, Floppy
117 * 12 softint-12, Keyboard/Mouse, Serial
118 * 13 softint-13, VME/SBUS level 7, ISDN Audio
119 * 14 softint-14, per-processor counter/timer
120 * 15 softint-15, Asynchronous Errors (broadcast)
121 *
122 * Each interrupt source is masked distinctly in the sun4m interrupt
123 * registers. The PIL level alone is therefore ambiguous, since multiple
124 * interrupt sources map to a single PIL.
125 *
126 * This ambiguity is resolved in the 'intr' property for device nodes
127 * in the OF device tree. Each 'intr' property entry is composed of
128 * two 32-bit words. The first word is the IRQ priority value, which
129 * is what we're intersted in. The second word is the IRQ vector, which
130 * is unused.
131 *
132 * The low 4 bits of the IRQ priority indicate the PIL, and the upper
133 * 4 bits indicate onboard vs. SBUS leveled vs. VME leveled. 0x20
134 * means onboard, 0x30 means SBUS leveled, and 0x40 means VME leveled.
135 *
136 * For example, an 'intr' IRQ priority value of 0x24 is onboard SCSI
137 * whereas a value of 0x33 is SBUS level 2. Here are some sample
138 * 'intr' property IRQ priority values from ss4, ss5, ss10, ss20, and
139 * Tadpole S3 GX systems.
140 *
141 * esp: 0x24 onboard ESP SCSI
142 * le: 0x26 onboard Lance ETHERNET
143 * p9100: 0x32 SBUS level 1 P9100 video
144 * bpp: 0x33 SBUS level 2 BPP parallel port device
145 * DBRI: 0x39 SBUS level 5 DBRI ISDN audio
146 * SUNW,leo: 0x39 SBUS level 5 LEO video
147 * pcmcia: 0x3b SBUS level 6 PCMCIA controller
148 * uctrl: 0x3b SBUS level 6 UCTRL device
149 * modem: 0x3d SBUS level 7 MODEM
150 * zs: 0x2c onboard keyboard/mouse/serial
151 * floppy: 0x2b onboard Floppy
152 * power: 0x22 onboard power device (XXX unknown mask bit XXX)
153 */
154
155static unsigned long irq_mask[0x50] = { 158static unsigned long irq_mask[0x50] = {
156 /* SMP */ 159 /* SMP */
157 0, SUN4M_SOFT_INT(1), 160 0, SUN4M_SOFT_INT(1),
@@ -193,7 +196,7 @@ static unsigned long irq_mask[0x50] = {
193static unsigned long sun4m_get_irqmask(unsigned int irq) 196static unsigned long sun4m_get_irqmask(unsigned int irq)
194{ 197{
195 unsigned long mask; 198 unsigned long mask;
196 199
197 if (irq < 0x50) 200 if (irq < 0x50)
198 mask = irq_mask[irq]; 201 mask = irq_mask[irq];
199 else 202 else
@@ -217,7 +220,7 @@ static void sun4m_disable_irq(unsigned int irq_nr)
217 sbus_writel(mask, &sun4m_irq_global->mask_set); 220 sbus_writel(mask, &sun4m_irq_global->mask_set);
218 else 221 else
219 sbus_writel(mask, &sun4m_irq_percpu[cpu]->set); 222 sbus_writel(mask, &sun4m_irq_percpu[cpu]->set);
220 local_irq_restore(flags); 223 local_irq_restore(flags);
221} 224}
222 225
223static void sun4m_enable_irq(unsigned int irq_nr) 226static void sun4m_enable_irq(unsigned int irq_nr)
@@ -226,17 +229,17 @@ static void sun4m_enable_irq(unsigned int irq_nr)
226 int cpu = smp_processor_id(); 229 int cpu = smp_processor_id();
227 230
228 /* Dreadful floppy hack. When we use 0x2b instead of 231 /* Dreadful floppy hack. When we use 0x2b instead of
229 * 0x0b the system blows (it starts to whistle!). 232 * 0x0b the system blows (it starts to whistle!).
230 * So we continue to use 0x0b. Fixme ASAP. --P3 233 * So we continue to use 0x0b. Fixme ASAP. --P3
231 */ 234 */
232 if (irq_nr != 0x0b) { 235 if (irq_nr != 0x0b) {
233 mask = sun4m_get_irqmask(irq_nr); 236 mask = sun4m_get_irqmask(irq_nr);
234 local_irq_save(flags); 237 local_irq_save(flags);
235 if (irq_nr > 15) 238 if (irq_nr > 15)
236 sbus_writel(mask, &sun4m_irq_global->mask_clear); 239 sbus_writel(mask, &sun4m_irq_global->mask_clear);
237 else 240 else
238 sbus_writel(mask, &sun4m_irq_percpu[cpu]->clear); 241 sbus_writel(mask, &sun4m_irq_percpu[cpu]->clear);
239 local_irq_restore(flags); 242 local_irq_restore(flags);
240 } else { 243 } else {
241 local_irq_save(flags); 244 local_irq_save(flags);
242 sbus_writel(SUN4M_INT_FLOPPY, &sun4m_irq_global->mask_clear); 245 sbus_writel(SUN4M_INT_FLOPPY, &sun4m_irq_global->mask_clear);
@@ -260,7 +263,7 @@ static unsigned long cpu_pil_to_imask[16] = {
260/*12*/ SUN4M_INT_SERIAL | SUN4M_INT_KBDMS, 263/*12*/ SUN4M_INT_SERIAL | SUN4M_INT_KBDMS,
261/*13*/ SUN4M_INT_SBUS(6) | SUN4M_INT_VME(6) | SUN4M_INT_AUDIO, 264/*13*/ SUN4M_INT_SBUS(6) | SUN4M_INT_VME(6) | SUN4M_INT_AUDIO,
262/*14*/ SUN4M_INT_E14, 265/*14*/ SUN4M_INT_E14,
263/*15*/ SUN4M_INT_ERROR 266/*15*/ SUN4M_INT_ERROR,
264}; 267};
265 268
266/* We assume the caller has disabled local interrupts when these are called, 269/* We assume the caller has disabled local interrupts when these are called,
@@ -280,12 +283,14 @@ static void sun4m_enable_pil_irq(unsigned int pil)
280static void sun4m_send_ipi(int cpu, int level) 283static void sun4m_send_ipi(int cpu, int level)
281{ 284{
282 unsigned long mask = sun4m_get_irqmask(level); 285 unsigned long mask = sun4m_get_irqmask(level);
286
283 sbus_writel(mask, &sun4m_irq_percpu[cpu]->set); 287 sbus_writel(mask, &sun4m_irq_percpu[cpu]->set);
284} 288}
285 289
286static void sun4m_clear_ipi(int cpu, int level) 290static void sun4m_clear_ipi(int cpu, int level)
287{ 291{
288 unsigned long mask = sun4m_get_irqmask(level); 292 unsigned long mask = sun4m_get_irqmask(level);
293
289 sbus_writel(mask, &sun4m_irq_percpu[cpu]->clear); 294 sbus_writel(mask, &sun4m_irq_percpu[cpu]->clear);
290} 295}
291 296
@@ -314,7 +319,7 @@ struct sun4m_timer_global {
314 319
315static struct sun4m_timer_global __iomem *timers_global; 320static struct sun4m_timer_global __iomem *timers_global;
316 321
317#define TIMER_IRQ (OBP_INT_LEVEL_ONBOARD | 10) 322#define TIMER_IRQ (OBP_INT_LEVEL_ONBOARD | 10)
318 323
319unsigned int lvl14_resolution = (((1000000/HZ) + 1) << 10); 324unsigned int lvl14_resolution = (((1000000/HZ) + 1) << 10);
320 325
@@ -407,7 +412,6 @@ static void __init sun4m_init_timers(irq_handler_t counter_fn)
407#ifdef CONFIG_SMP 412#ifdef CONFIG_SMP
408 { 413 {
409 unsigned long flags; 414 unsigned long flags;
410 extern unsigned long lvl14_save[4];
411 struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (14 - 1)]; 415 struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (14 - 1)];
412 416
413 /* For SMP we use the level 14 ticker, however the bootup code 417 /* For SMP we use the level 14 ticker, however the bootup code