2 * Copyright (C) 2014 Mans Rullgard <mans@mansr.com>
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
10 #include <linux/init.h>
11 #include <linux/irq.h>
12 #include <linux/irqchip.h>
13 #include <linux/irqchip/chained_irq.h>
14 #include <linux/ioport.h>
16 #include <linux/of_address.h>
17 #include <linux/of_irq.h>
18 #include <linux/slab.h>
20 #define IRQ0_CTL_BASE 0x0000
21 #define IRQ1_CTL_BASE 0x0100
22 #define EDGE_CTL_BASE 0x0200
23 #define IRQ2_CTL_BASE 0x0300
25 #define IRQ_CTL_HI 0x18
26 #define EDGE_CTL_HI 0x20
28 #define IRQ_STATUS 0x00
29 #define IRQ_RAWSTAT 0x04
30 #define IRQ_EN_SET 0x08
31 #define IRQ_EN_CLR 0x0c
32 #define IRQ_SOFT_SET 0x10
33 #define IRQ_SOFT_CLR 0x14
35 #define EDGE_STATUS 0x00
36 #define EDGE_RAWSTAT 0x04
37 #define EDGE_CFG_RISE 0x08
38 #define EDGE_CFG_FALL 0x0c
39 #define EDGE_CFG_RISE_SET 0x10
40 #define EDGE_CFG_RISE_CLR 0x14
41 #define EDGE_CFG_FALL_SET 0x18
42 #define EDGE_CFG_FALL_CLR 0x1c
44 struct tangox_irq_chip
{
49 static inline u32
intc_readl(struct tangox_irq_chip
*chip
, int reg
)
51 return readl_relaxed(chip
->base
+ reg
);
54 static inline void intc_writel(struct tangox_irq_chip
*chip
, int reg
, u32 val
)
56 writel_relaxed(val
, chip
->base
+ reg
);
59 static void tangox_dispatch_irqs(struct irq_domain
*dom
, unsigned int status
,
66 hwirq
= __ffs(status
);
67 virq
= irq_find_mapping(dom
, base
+ hwirq
);
69 generic_handle_irq(virq
);
70 status
&= ~BIT(hwirq
);
74 static void tangox_irq_handler(struct irq_desc
*desc
)
76 struct irq_domain
*dom
= irq_desc_get_handler_data(desc
);
77 struct irq_chip
*host_chip
= irq_desc_get_chip(desc
);
78 struct tangox_irq_chip
*chip
= dom
->host_data
;
79 unsigned int status_lo
, status_hi
;
81 chained_irq_enter(host_chip
, desc
);
83 status_lo
= intc_readl(chip
, chip
->ctl
+ IRQ_STATUS
);
84 status_hi
= intc_readl(chip
, chip
->ctl
+ IRQ_CTL_HI
+ IRQ_STATUS
);
86 tangox_dispatch_irqs(dom
, status_lo
, 0);
87 tangox_dispatch_irqs(dom
, status_hi
, 32);
89 chained_irq_exit(host_chip
, desc
);
92 static int tangox_irq_set_type(struct irq_data
*d
, unsigned int flow_type
)
94 struct irq_chip_generic
*gc
= irq_data_get_irq_chip_data(d
);
95 struct tangox_irq_chip
*chip
= gc
->domain
->host_data
;
96 struct irq_chip_regs
*regs
= &gc
->chip_types
[0].regs
;
98 switch (flow_type
& IRQ_TYPE_SENSE_MASK
) {
99 case IRQ_TYPE_EDGE_RISING
:
100 intc_writel(chip
, regs
->type
+ EDGE_CFG_RISE_SET
, d
->mask
);
101 intc_writel(chip
, regs
->type
+ EDGE_CFG_FALL_CLR
, d
->mask
);
104 case IRQ_TYPE_EDGE_FALLING
:
105 intc_writel(chip
, regs
->type
+ EDGE_CFG_RISE_CLR
, d
->mask
);
106 intc_writel(chip
, regs
->type
+ EDGE_CFG_FALL_SET
, d
->mask
);
109 case IRQ_TYPE_LEVEL_HIGH
:
110 intc_writel(chip
, regs
->type
+ EDGE_CFG_RISE_CLR
, d
->mask
);
111 intc_writel(chip
, regs
->type
+ EDGE_CFG_FALL_CLR
, d
->mask
);
114 case IRQ_TYPE_LEVEL_LOW
:
115 intc_writel(chip
, regs
->type
+ EDGE_CFG_RISE_SET
, d
->mask
);
116 intc_writel(chip
, regs
->type
+ EDGE_CFG_FALL_SET
, d
->mask
);
120 pr_err("Invalid trigger mode %x for IRQ %d\n",
125 return irq_setup_alt_chip(d
, flow_type
);
128 static void __init
tangox_irq_init_chip(struct irq_chip_generic
*gc
,
129 unsigned long ctl_offs
,
130 unsigned long edge_offs
)
132 struct tangox_irq_chip
*chip
= gc
->domain
->host_data
;
133 struct irq_chip_type
*ct
= gc
->chip_types
;
134 unsigned long ctl_base
= chip
->ctl
+ ctl_offs
;
135 unsigned long edge_base
= EDGE_CTL_BASE
+ edge_offs
;
138 gc
->reg_base
= chip
->base
;
141 for (i
= 0; i
< 2; i
++) {
142 ct
[i
].chip
.irq_ack
= irq_gc_ack_set_bit
;
143 ct
[i
].chip
.irq_mask
= irq_gc_mask_disable_reg
;
144 ct
[i
].chip
.irq_mask_ack
= irq_gc_mask_disable_and_ack_set
;
145 ct
[i
].chip
.irq_unmask
= irq_gc_unmask_enable_reg
;
146 ct
[i
].chip
.irq_set_type
= tangox_irq_set_type
;
147 ct
[i
].chip
.name
= gc
->domain
->name
;
149 ct
[i
].regs
.enable
= ctl_base
+ IRQ_EN_SET
;
150 ct
[i
].regs
.disable
= ctl_base
+ IRQ_EN_CLR
;
151 ct
[i
].regs
.ack
= edge_base
+ EDGE_RAWSTAT
;
152 ct
[i
].regs
.type
= edge_base
;
155 ct
[0].type
= IRQ_TYPE_LEVEL_MASK
;
156 ct
[0].handler
= handle_level_irq
;
158 ct
[1].type
= IRQ_TYPE_EDGE_BOTH
;
159 ct
[1].handler
= handle_edge_irq
;
161 intc_writel(chip
, ct
->regs
.disable
, 0xffffffff);
162 intc_writel(chip
, ct
->regs
.ack
, 0xffffffff);
165 static void __init
tangox_irq_domain_init(struct irq_domain
*dom
)
167 struct irq_chip_generic
*gc
;
170 for (i
= 0; i
< 2; i
++) {
171 gc
= irq_get_domain_generic_chip(dom
, i
* 32);
172 tangox_irq_init_chip(gc
, i
* IRQ_CTL_HI
, i
* EDGE_CTL_HI
);
176 static int __init
tangox_irq_init(void __iomem
*base
, struct resource
*baseres
,
177 struct device_node
*node
)
179 struct tangox_irq_chip
*chip
;
180 struct irq_domain
*dom
;
185 irq
= irq_of_parse_and_map(node
, 0);
187 panic("%pOFn: failed to get IRQ", node
);
189 err
= of_address_to_resource(node
, 0, &res
);
191 panic("%pOFn: failed to get address", node
);
193 chip
= kzalloc(sizeof(*chip
), GFP_KERNEL
);
194 chip
->ctl
= res
.start
- baseres
->start
;
197 dom
= irq_domain_add_linear(node
, 64, &irq_generic_chip_ops
, chip
);
199 panic("%pOFn: failed to create irqdomain", node
);
201 err
= irq_alloc_domain_generic_chips(dom
, 32, 2, node
->name
,
202 handle_level_irq
, 0, 0, 0);
204 panic("%pOFn: failed to allocate irqchip", node
);
206 tangox_irq_domain_init(dom
);
208 irq_set_chained_handler_and_data(irq
, tangox_irq_handler
, dom
);
213 static int __init
tangox_of_irq_init(struct device_node
*node
,
214 struct device_node
*parent
)
216 struct device_node
*c
;
220 base
= of_iomap(node
, 0);
222 panic("%pOFn: of_iomap failed", node
);
224 of_address_to_resource(node
, 0, &res
);
226 for_each_child_of_node(node
, c
)
227 tangox_irq_init(base
, &res
, c
);
231 IRQCHIP_DECLARE(tangox_intc
, "sigma,smp8642-intc", tangox_of_irq_init
);