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>
15 #include <linux/of_address.h>
16 #include <linux/of_irq.h>
18 #include <asm/mach/irq.h>
19 #include <asm/exception.h>
23 #define IO_STATUS 0x000
24 #define IO_RAW_STATUS 0x004
25 #define IO_ENABLE 0x008
26 #define IO_DISABLE 0x00C
27 #define IO_CURRENT 0x020
28 #define IO_RESET 0x028
29 #define IO_MAX_PRIOTY 0x02C
31 #define IO_IRQ_BASE 0x000
32 #define IO_FIQ_BASE 0x100
34 #define IO_INVERT_SEL 0x200
35 #define IO_STICKY_SEL 0x204
36 #define IO_PRIORITY_SEL 0x300
39 #define FIQ_START MAX_INTRS
41 static struct irq_domain
*zevio_irq_domain
;
42 static void __iomem
*zevio_irq_io
;
44 static void zevio_irq_ack(struct irq_data
*irqd
)
46 struct irq_chip_generic
*gc
= irq_data_get_irq_chip_data(irqd
);
47 struct irq_chip_regs
*regs
=
48 &container_of(irqd
->chip
, struct irq_chip_type
, chip
)->regs
;
50 readl(gc
->reg_base
+ regs
->ack
);
53 static asmlinkage
void __exception_irq_entry
zevio_handle_irq(struct pt_regs
*regs
)
57 while (readl(zevio_irq_io
+ IO_STATUS
)) {
58 irqnr
= readl(zevio_irq_io
+ IO_CURRENT
);
59 irqnr
= irq_find_mapping(zevio_irq_domain
, irqnr
);
60 handle_IRQ(irqnr
, regs
);
64 static void __init
zevio_init_irq_base(void __iomem
*base
)
66 /* Disable all interrupts */
67 writel(~0, base
+ IO_DISABLE
);
69 /* Accept interrupts of all priorities */
70 writel(0xF, base
+ IO_MAX_PRIOTY
);
72 /* Reset existing interrupts */
73 readl(base
+ IO_RESET
);
76 static int __init
zevio_of_init(struct device_node
*node
,
77 struct device_node
*parent
)
79 unsigned int clr
= IRQ_NOREQUEST
| IRQ_NOPROBE
| IRQ_NOAUTOEN
;
80 struct irq_chip_generic
*gc
;
83 if (WARN_ON(zevio_irq_io
|| zevio_irq_domain
))
86 zevio_irq_io
= of_iomap(node
, 0);
87 BUG_ON(!zevio_irq_io
);
89 /* Do not invert interrupt status bits */
90 writel(~0, zevio_irq_io
+ IO_INVERT_SEL
);
92 /* Disable sticky interrupts */
93 writel(0, zevio_irq_io
+ IO_STICKY_SEL
);
95 /* We don't use IRQ priorities. Set each IRQ to highest priority. */
96 memset_io(zevio_irq_io
+ IO_PRIORITY_SEL
, 0, MAX_INTRS
* sizeof(u32
));
98 /* Init IRQ and FIQ */
99 zevio_init_irq_base(zevio_irq_io
+ IO_IRQ_BASE
);
100 zevio_init_irq_base(zevio_irq_io
+ IO_FIQ_BASE
);
102 zevio_irq_domain
= irq_domain_add_linear(node
, MAX_INTRS
,
103 &irq_generic_chip_ops
, NULL
);
104 BUG_ON(!zevio_irq_domain
);
106 ret
= irq_alloc_domain_generic_chips(zevio_irq_domain
, MAX_INTRS
, 1,
107 "zevio_intc", handle_level_irq
,
108 clr
, 0, IRQ_GC_INIT_MASK_CACHE
);
111 gc
= irq_get_domain_generic_chip(zevio_irq_domain
, 0);
112 gc
->reg_base
= zevio_irq_io
;
113 gc
->chip_types
[0].chip
.irq_ack
= zevio_irq_ack
;
114 gc
->chip_types
[0].chip
.irq_mask
= irq_gc_mask_disable_reg
;
115 gc
->chip_types
[0].chip
.irq_unmask
= irq_gc_unmask_enable_reg
;
116 gc
->chip_types
[0].regs
.mask
= IO_IRQ_BASE
+ IO_ENABLE
;
117 gc
->chip_types
[0].regs
.enable
= IO_IRQ_BASE
+ IO_ENABLE
;
118 gc
->chip_types
[0].regs
.disable
= IO_IRQ_BASE
+ IO_DISABLE
;
119 gc
->chip_types
[0].regs
.ack
= IO_IRQ_BASE
+ IO_RESET
;
121 set_handle_irq(zevio_handle_irq
);
123 pr_info("TI-NSPIRE classic IRQ controller\n");
127 IRQCHIP_DECLARE(zevio_irq
, "lsi,zevio-intc", zevio_of_init
);