2 * linux/drivers/irqchip/irq-zevio.c
4 * Copyright (C) 2013 Daniel Tang <tangrs@tangrs.id.au>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2, as
8 * published by the Free Software Foundation.
13 #include <linux/irq.h>
14 #include <linux/irqchip.h>
16 #include <linux/of_address.h>
17 #include <linux/of_irq.h>
19 #include <asm/mach/irq.h>
20 #include <asm/exception.h>
22 #define IO_STATUS 0x000
23 #define IO_RAW_STATUS 0x004
24 #define IO_ENABLE 0x008
25 #define IO_DISABLE 0x00C
26 #define IO_CURRENT 0x020
27 #define IO_RESET 0x028
28 #define IO_MAX_PRIOTY 0x02C
30 #define IO_IRQ_BASE 0x000
31 #define IO_FIQ_BASE 0x100
33 #define IO_INVERT_SEL 0x200
34 #define IO_STICKY_SEL 0x204
35 #define IO_PRIORITY_SEL 0x300
38 #define FIQ_START MAX_INTRS
40 static struct irq_domain
*zevio_irq_domain
;
41 static void __iomem
*zevio_irq_io
;
43 static void zevio_irq_ack(struct irq_data
*irqd
)
45 struct irq_chip_generic
*gc
= irq_data_get_irq_chip_data(irqd
);
46 struct irq_chip_regs
*regs
= &irq_data_get_chip_type(irqd
)->regs
;
48 readl(gc
->reg_base
+ regs
->ack
);
51 static void __exception_irq_entry
zevio_handle_irq(struct pt_regs
*regs
)
55 while (readl(zevio_irq_io
+ IO_STATUS
)) {
56 irqnr
= readl(zevio_irq_io
+ IO_CURRENT
);
57 handle_domain_irq(zevio_irq_domain
, irqnr
, regs
);
61 static void __init
zevio_init_irq_base(void __iomem
*base
)
63 /* Disable all interrupts */
64 writel(~0, base
+ IO_DISABLE
);
66 /* Accept interrupts of all priorities */
67 writel(0xF, base
+ IO_MAX_PRIOTY
);
69 /* Reset existing interrupts */
70 readl(base
+ IO_RESET
);
73 static int __init
zevio_of_init(struct device_node
*node
,
74 struct device_node
*parent
)
76 unsigned int clr
= IRQ_NOREQUEST
| IRQ_NOPROBE
| IRQ_NOAUTOEN
;
77 struct irq_chip_generic
*gc
;
80 if (WARN_ON(zevio_irq_io
|| zevio_irq_domain
))
83 zevio_irq_io
= of_iomap(node
, 0);
84 BUG_ON(!zevio_irq_io
);
86 /* Do not invert interrupt status bits */
87 writel(~0, zevio_irq_io
+ IO_INVERT_SEL
);
89 /* Disable sticky interrupts */
90 writel(0, zevio_irq_io
+ IO_STICKY_SEL
);
92 /* We don't use IRQ priorities. Set each IRQ to highest priority. */
93 memset_io(zevio_irq_io
+ IO_PRIORITY_SEL
, 0, MAX_INTRS
* sizeof(u32
));
95 /* Init IRQ and FIQ */
96 zevio_init_irq_base(zevio_irq_io
+ IO_IRQ_BASE
);
97 zevio_init_irq_base(zevio_irq_io
+ IO_FIQ_BASE
);
99 zevio_irq_domain
= irq_domain_add_linear(node
, MAX_INTRS
,
100 &irq_generic_chip_ops
, NULL
);
101 BUG_ON(!zevio_irq_domain
);
103 ret
= irq_alloc_domain_generic_chips(zevio_irq_domain
, MAX_INTRS
, 1,
104 "zevio_intc", handle_level_irq
,
105 clr
, 0, IRQ_GC_INIT_MASK_CACHE
);
108 gc
= irq_get_domain_generic_chip(zevio_irq_domain
, 0);
109 gc
->reg_base
= zevio_irq_io
;
110 gc
->chip_types
[0].chip
.irq_ack
= zevio_irq_ack
;
111 gc
->chip_types
[0].chip
.irq_mask
= irq_gc_mask_disable_reg
;
112 gc
->chip_types
[0].chip
.irq_unmask
= irq_gc_unmask_enable_reg
;
113 gc
->chip_types
[0].regs
.mask
= IO_IRQ_BASE
+ IO_ENABLE
;
114 gc
->chip_types
[0].regs
.enable
= IO_IRQ_BASE
+ IO_ENABLE
;
115 gc
->chip_types
[0].regs
.disable
= IO_IRQ_BASE
+ IO_DISABLE
;
116 gc
->chip_types
[0].regs
.ack
= IO_IRQ_BASE
+ IO_RESET
;
118 set_handle_irq(zevio_handle_irq
);
120 pr_info("TI-NSPIRE classic IRQ controller\n");
124 IRQCHIP_DECLARE(zevio_irq
, "lsi,zevio-intc", zevio_of_init
);