2 * linux/arch/sh/boards/ec3104/irq.c
3 * EC3104 companion chip support
5 * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
11 #include <asm/ec3104/ec3104.h>
13 /* This is for debugging mostly; here's the table that I intend to keep
16 * index function base addr power interrupt bit
17 * 0 power b0ec0000 --- 00000001 (unused)
18 * 1 irqs b0ec1000 --- 00000002 (unused)
19 * 2 ?? b0ec2000 b0ec0008 00000004
20 * 3 PS2 (1) b0ec3000 b0ec000c 00000008
21 * 4 PS2 (2) b0ec4000 b0ec0010 00000010
22 * 5 ?? b0ec5000 b0ec0014 00000020
23 * 6 I2C b0ec6000 b0ec0018 00000040
24 * 7 serial (1) b0ec7000 b0ec001c 00000080
25 * 8 serial (2) b0ec8000 b0ec0020 00000100
26 * 9 serial (3) b0ec9000 b0ec0024 00000200
27 * 10 serial (4) b0eca000 b0ec0028 00000400
28 * 12 GPIO (1) b0ecc000 b0ec0030
29 * 13 GPIO (2) b0ecc000 b0ec0030
30 * 16 pcmcia (1) b0ed0000 b0ec0040 00010000
31 * 17 pcmcia (2) b0ed1000 b0ec0044 00020000
34 /* I used the register names from another interrupt controller I worked with,
35 * since it seems to be identical to the ec3104 except that all bits are
38 * IRR: Interrupt Request Register (pending and enabled interrupts)
39 * IMR: Interrupt Mask Register (which interrupts are enabled)
40 * IPR: Interrupt Pending Register (pending interrupts, even disabled ones)
42 * 0 bits mean pending or enabled, 1 bits mean not pending or disabled. all
43 * IRQs seem to be level-triggered.
46 #define EC3104_IRR (EC3104_BASE + 0x1000)
47 #define EC3104_IMR (EC3104_BASE + 0x1004)
48 #define EC3104_IPR (EC3104_BASE + 0x1008)
50 #define ctrl_readl(addr) (*(volatile u32 *)(addr))
51 #define ctrl_writel(data,addr) (*(volatile u32 *)(addr) = (data))
52 #define ctrl_readb(addr) (*(volatile u8 *)(addr))
54 static char *ec3104_name(unsigned index
)
58 return "power management";
84 sprintf(buf
, "unknown (%d)", index
);
91 int get_pending_interrupts(char *buf
)
97 p
+= sprintf(p
, "pending: (");
99 ipr
= ctrl_inl(EC3104_IPR
);
101 for (bit
= 1; bit
< 32; bit
++)
102 if (!(ipr
& (1<<bit
)))
103 p
+= sprintf(p
, "%s ", ec3104_name(bit
));
105 p
+= sprintf(p
, ")\n");
110 static inline u32
ec3104_irq2mask(unsigned int irq
)
112 return (1 << (irq
- EC3104_IRQBASE
));
115 static inline void mask_ec3104_irq(unsigned int irq
)
119 mask
= ctrl_readl(EC3104_IMR
);
121 mask
|= ec3104_irq2mask(irq
);
123 ctrl_writel(mask
, EC3104_IMR
);
126 static inline void unmask_ec3104_irq(unsigned int irq
)
130 mask
= ctrl_readl(EC3104_IMR
);
132 mask
&= ~ec3104_irq2mask(irq
);
134 ctrl_writel(mask
, EC3104_IMR
);
137 static void disable_ec3104_irq(unsigned int irq
)
139 mask_ec3104_irq(irq
);
142 static void enable_ec3104_irq(unsigned int irq
)
144 unmask_ec3104_irq(irq
);
147 static void mask_and_ack_ec3104_irq(unsigned int irq
)
149 mask_ec3104_irq(irq
);
152 static void end_ec3104_irq(unsigned int irq
)
154 if (!(irq_desc
[irq
].status
& (IRQ_DISABLED
|IRQ_INPROGRESS
)))
155 unmask_ec3104_irq(irq
);
158 static unsigned int startup_ec3104_irq(unsigned int irq
)
160 unmask_ec3104_irq(irq
);
165 static void shutdown_ec3104_irq(unsigned int irq
)
167 mask_ec3104_irq(irq
);
171 static struct hw_interrupt_type ec3104_int
= {
172 .typename
= "EC3104",
173 .enable
= enable_ec3104_irq
,
174 .disable
= disable_ec3104_irq
,
175 .ack
= mask_and_ack_ec3104_irq
,
176 .end
= end_ec3104_irq
,
177 .startup
= startup_ec3104_irq
,
178 .shutdown
= shutdown_ec3104_irq
,
181 /* Yuck. the _demux API is ugly */
182 int ec3104_irq_demux(int irq
)
184 if (irq
== EC3104_IRQ
) {
187 mask
= ctrl_readl(EC3104_IRR
);
189 if (mask
== 0xffffffff)
192 return EC3104_IRQBASE
+ ffz(mask
);