123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196 |
- /*
- * linux/arch/sh/boards/ec3104/irq.c
- * EC3104 companion chip support
- *
- * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
- *
- */
- #include <asm/io.h>
- #include <asm/irq.h>
- #include <asm/ec3104/ec3104.h>
- /* This is for debugging mostly; here's the table that I intend to keep
- * in here:
- *
- * index function base addr power interrupt bit
- * 0 power b0ec0000 --- 00000001 (unused)
- * 1 irqs b0ec1000 --- 00000002 (unused)
- * 2 ?? b0ec2000 b0ec0008 00000004
- * 3 PS2 (1) b0ec3000 b0ec000c 00000008
- * 4 PS2 (2) b0ec4000 b0ec0010 00000010
- * 5 ?? b0ec5000 b0ec0014 00000020
- * 6 I2C b0ec6000 b0ec0018 00000040
- * 7 serial (1) b0ec7000 b0ec001c 00000080
- * 8 serial (2) b0ec8000 b0ec0020 00000100
- * 9 serial (3) b0ec9000 b0ec0024 00000200
- * 10 serial (4) b0eca000 b0ec0028 00000400
- * 12 GPIO (1) b0ecc000 b0ec0030
- * 13 GPIO (2) b0ecc000 b0ec0030
- * 16 pcmcia (1) b0ed0000 b0ec0040 00010000
- * 17 pcmcia (2) b0ed1000 b0ec0044 00020000
- */
- /* I used the register names from another interrupt controller I worked with,
- * since it seems to be identical to the ec3104 except that all bits are
- * inverted:
- *
- * IRR: Interrupt Request Register (pending and enabled interrupts)
- * IMR: Interrupt Mask Register (which interrupts are enabled)
- * IPR: Interrupt Pending Register (pending interrupts, even disabled ones)
- *
- * 0 bits mean pending or enabled, 1 bits mean not pending or disabled. all
- * IRQs seem to be level-triggered.
- */
- #define EC3104_IRR (EC3104_BASE + 0x1000)
- #define EC3104_IMR (EC3104_BASE + 0x1004)
- #define EC3104_IPR (EC3104_BASE + 0x1008)
- #define ctrl_readl(addr) (*(volatile u32 *)(addr))
- #define ctrl_writel(data,addr) (*(volatile u32 *)(addr) = (data))
- #define ctrl_readb(addr) (*(volatile u8 *)(addr))
- static char *ec3104_name(unsigned index)
- {
- switch(index) {
- case 0:
- return "power management";
- case 1:
- return "interrupts";
- case 3:
- return "PS2 (1)";
- case 4:
- return "PS2 (2)";
- case 5:
- return "I2C (1)";
- case 6:
- return "I2C (2)";
- case 7:
- return "serial (1)";
- case 8:
- return "serial (2)";
- case 9:
- return "serial (3)";
- case 10:
- return "serial (4)";
- case 16:
- return "pcmcia (1)";
- case 17:
- return "pcmcia (2)";
- default: {
- static char buf[32];
- sprintf(buf, "unknown (%d)", index);
- return buf;
- }
- }
- }
- int get_pending_interrupts(char *buf)
- {
- u32 ipr;
- u32 bit;
- char *p = buf;
- p += sprintf(p, "pending: (");
- ipr = ctrl_inl(EC3104_IPR);
- for (bit = 1; bit < 32; bit++)
- if (!(ipr & (1<<bit)))
- p += sprintf(p, "%s ", ec3104_name(bit));
- p += sprintf(p, ")\n");
- return p - buf;
- }
- static inline u32 ec3104_irq2mask(unsigned int irq)
- {
- return (1 << (irq - EC3104_IRQBASE));
- }
- static inline void mask_ec3104_irq(unsigned int irq)
- {
- u32 mask;
- mask = ctrl_readl(EC3104_IMR);
- mask |= ec3104_irq2mask(irq);
- ctrl_writel(mask, EC3104_IMR);
- }
- static inline void unmask_ec3104_irq(unsigned int irq)
- {
- u32 mask;
- mask = ctrl_readl(EC3104_IMR);
- mask &= ~ec3104_irq2mask(irq);
- ctrl_writel(mask, EC3104_IMR);
- }
- static void disable_ec3104_irq(unsigned int irq)
- {
- mask_ec3104_irq(irq);
- }
- static void enable_ec3104_irq(unsigned int irq)
- {
- unmask_ec3104_irq(irq);
- }
- static void mask_and_ack_ec3104_irq(unsigned int irq)
- {
- mask_ec3104_irq(irq);
- }
- static void end_ec3104_irq(unsigned int irq)
- {
- if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
- unmask_ec3104_irq(irq);
- }
- static unsigned int startup_ec3104_irq(unsigned int irq)
- {
- unmask_ec3104_irq(irq);
- return 0;
- }
- static void shutdown_ec3104_irq(unsigned int irq)
- {
- mask_ec3104_irq(irq);
- }
- static struct hw_interrupt_type ec3104_int = {
- .typename = "EC3104",
- .enable = enable_ec3104_irq,
- .disable = disable_ec3104_irq,
- .ack = mask_and_ack_ec3104_irq,
- .end = end_ec3104_irq,
- .startup = startup_ec3104_irq,
- .shutdown = shutdown_ec3104_irq,
- };
- /* Yuck. the _demux API is ugly */
- int ec3104_irq_demux(int irq)
- {
- if (irq == EC3104_IRQ) {
- unsigned int mask;
- mask = ctrl_readl(EC3104_IRR);
- if (mask == 0xffffffff)
- return EC3104_IRQ;
- else
- return EC3104_IRQBASE + ffz(mask);
- }
- return irq;
- }
|