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
=
47 &container_of(irqd
->chip
, struct irq_chip_type
, chip
)->regs
;
49 readl(gc
->reg_base
+ regs
->ack
);
52 static void __exception_irq_entry
zevio_handle_irq(struct pt_regs
*regs
)
56 while (readl(zevio_irq_io
+ IO_STATUS
)) {
57 irqnr
= readl(zevio_irq_io
+ IO_CURRENT
);
58 handle_domain_irq(zevio_irq_domain
, irqnr
, regs
);
62 static void __init
zevio_init_irq_base(void __iomem
*base
)
64 /* Disable all interrupts */
65 writel(~0, base
+ IO_DISABLE
);
67 /* Accept interrupts of all priorities */
68 writel(0xF, base
+ IO_MAX_PRIOTY
);
70 /* Reset existing interrupts */
71 readl(base
+ IO_RESET
);
74 static int __init
zevio_of_init(struct device_node
*node
,
75 struct device_node
*parent
)
77 unsigned int clr
= IRQ_NOREQUEST
| IRQ_NOPROBE
| IRQ_NOAUTOEN
;
78 struct irq_chip_generic
*gc
;
81 if (WARN_ON(zevio_irq_io
|| zevio_irq_domain
))
84 zevio_irq_io
= of_iomap(node
, 0);
85 BUG_ON(!zevio_irq_io
);
87 /* Do not invert interrupt status bits */
88 writel(~0, zevio_irq_io
+ IO_INVERT_SEL
);
90 /* Disable sticky interrupts */
91 writel(0, zevio_irq_io
+ IO_STICKY_SEL
);
93 /* We don't use IRQ priorities. Set each IRQ to highest priority. */
94 memset_io(zevio_irq_io
+ IO_PRIORITY_SEL
, 0, MAX_INTRS
* sizeof(u32
));
96 /* Init IRQ and FIQ */
97 zevio_init_irq_base(zevio_irq_io
+ IO_IRQ_BASE
);
98 zevio_init_irq_base(zevio_irq_io
+ IO_FIQ_BASE
);
100 zevio_irq_domain
= irq_domain_add_linear(node
, MAX_INTRS
,
101 &irq_generic_chip_ops
, NULL
);
102 BUG_ON(!zevio_irq_domain
);
104 ret
= irq_alloc_domain_generic_chips(zevio_irq_domain
, MAX_INTRS
, 1,
105 "zevio_intc", handle_level_irq
,
106 clr
, 0, IRQ_GC_INIT_MASK_CACHE
);
109 gc
= irq_get_domain_generic_chip(zevio_irq_domain
, 0);
110 gc
->reg_base
= zevio_irq_io
;
111 gc
->chip_types
[0].chip
.irq_ack
= zevio_irq_ack
;
112 gc
->chip_types
[0].chip
.irq_mask
= irq_gc_mask_disable_reg
;
113 gc
->chip_types
[0].chip
.irq_unmask
= irq_gc_unmask_enable_reg
;
114 gc
->chip_types
[0].regs
.mask
= IO_IRQ_BASE
+ IO_ENABLE
;
115 gc
->chip_types
[0].regs
.enable
= IO_IRQ_BASE
+ IO_ENABLE
;
116 gc
->chip_types
[0].regs
.disable
= IO_IRQ_BASE
+ IO_DISABLE
;
117 gc
->chip_types
[0].regs
.ack
= IO_IRQ_BASE
+ IO_RESET
;
119 set_handle_irq(zevio_handle_irq
);
121 pr_info("TI-NSPIRE classic IRQ controller\n");
125 IRQCHIP_DECLARE(zevio_irq
, "lsi,zevio-intc", zevio_of_init
);