1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2014 Mans Rullgard <mans@mansr.com>
6 #include <linux/init.h>
8 #include <linux/irqchip.h>
9 #include <linux/irqchip/chained_irq.h>
10 #include <linux/ioport.h>
12 #include <linux/of_address.h>
13 #include <linux/of_irq.h>
14 #include <linux/slab.h>
16 #define IRQ0_CTL_BASE 0x0000
17 #define IRQ1_CTL_BASE 0x0100
18 #define EDGE_CTL_BASE 0x0200
19 #define IRQ2_CTL_BASE 0x0300
21 #define IRQ_CTL_HI 0x18
22 #define EDGE_CTL_HI 0x20
24 #define IRQ_STATUS 0x00
25 #define IRQ_RAWSTAT 0x04
26 #define IRQ_EN_SET 0x08
27 #define IRQ_EN_CLR 0x0c
28 #define IRQ_SOFT_SET 0x10
29 #define IRQ_SOFT_CLR 0x14
31 #define EDGE_STATUS 0x00
32 #define EDGE_RAWSTAT 0x04
33 #define EDGE_CFG_RISE 0x08
34 #define EDGE_CFG_FALL 0x0c
35 #define EDGE_CFG_RISE_SET 0x10
36 #define EDGE_CFG_RISE_CLR 0x14
37 #define EDGE_CFG_FALL_SET 0x18
38 #define EDGE_CFG_FALL_CLR 0x1c
40 struct tangox_irq_chip
{
45 static inline u32
intc_readl(struct tangox_irq_chip
*chip
, int reg
)
47 return readl_relaxed(chip
->base
+ reg
);
50 static inline void intc_writel(struct tangox_irq_chip
*chip
, int reg
, u32 val
)
52 writel_relaxed(val
, chip
->base
+ reg
);
55 static void tangox_dispatch_irqs(struct irq_domain
*dom
, unsigned int status
,
62 hwirq
= __ffs(status
);
63 virq
= irq_find_mapping(dom
, base
+ hwirq
);
65 generic_handle_irq(virq
);
66 status
&= ~BIT(hwirq
);
70 static void tangox_irq_handler(struct irq_desc
*desc
)
72 struct irq_domain
*dom
= irq_desc_get_handler_data(desc
);
73 struct irq_chip
*host_chip
= irq_desc_get_chip(desc
);
74 struct tangox_irq_chip
*chip
= dom
->host_data
;
75 unsigned int status_lo
, status_hi
;
77 chained_irq_enter(host_chip
, desc
);
79 status_lo
= intc_readl(chip
, chip
->ctl
+ IRQ_STATUS
);
80 status_hi
= intc_readl(chip
, chip
->ctl
+ IRQ_CTL_HI
+ IRQ_STATUS
);
82 tangox_dispatch_irqs(dom
, status_lo
, 0);
83 tangox_dispatch_irqs(dom
, status_hi
, 32);
85 chained_irq_exit(host_chip
, desc
);
88 static int tangox_irq_set_type(struct irq_data
*d
, unsigned int flow_type
)
90 struct irq_chip_generic
*gc
= irq_data_get_irq_chip_data(d
);
91 struct tangox_irq_chip
*chip
= gc
->domain
->host_data
;
92 struct irq_chip_regs
*regs
= &gc
->chip_types
[0].regs
;
94 switch (flow_type
& IRQ_TYPE_SENSE_MASK
) {
95 case IRQ_TYPE_EDGE_RISING
:
96 intc_writel(chip
, regs
->type
+ EDGE_CFG_RISE_SET
, d
->mask
);
97 intc_writel(chip
, regs
->type
+ EDGE_CFG_FALL_CLR
, d
->mask
);
100 case IRQ_TYPE_EDGE_FALLING
:
101 intc_writel(chip
, regs
->type
+ EDGE_CFG_RISE_CLR
, d
->mask
);
102 intc_writel(chip
, regs
->type
+ EDGE_CFG_FALL_SET
, d
->mask
);
105 case IRQ_TYPE_LEVEL_HIGH
:
106 intc_writel(chip
, regs
->type
+ EDGE_CFG_RISE_CLR
, d
->mask
);
107 intc_writel(chip
, regs
->type
+ EDGE_CFG_FALL_CLR
, d
->mask
);
110 case IRQ_TYPE_LEVEL_LOW
:
111 intc_writel(chip
, regs
->type
+ EDGE_CFG_RISE_SET
, d
->mask
);
112 intc_writel(chip
, regs
->type
+ EDGE_CFG_FALL_SET
, d
->mask
);
116 pr_err("Invalid trigger mode %x for IRQ %d\n",
121 return irq_setup_alt_chip(d
, flow_type
);
124 static void __init
tangox_irq_init_chip(struct irq_chip_generic
*gc
,
125 unsigned long ctl_offs
,
126 unsigned long edge_offs
)
128 struct tangox_irq_chip
*chip
= gc
->domain
->host_data
;
129 struct irq_chip_type
*ct
= gc
->chip_types
;
130 unsigned long ctl_base
= chip
->ctl
+ ctl_offs
;
131 unsigned long edge_base
= EDGE_CTL_BASE
+ edge_offs
;
134 gc
->reg_base
= chip
->base
;
137 for (i
= 0; i
< 2; i
++) {
138 ct
[i
].chip
.irq_ack
= irq_gc_ack_set_bit
;
139 ct
[i
].chip
.irq_mask
= irq_gc_mask_disable_reg
;
140 ct
[i
].chip
.irq_mask_ack
= irq_gc_mask_disable_and_ack_set
;
141 ct
[i
].chip
.irq_unmask
= irq_gc_unmask_enable_reg
;
142 ct
[i
].chip
.irq_set_type
= tangox_irq_set_type
;
143 ct
[i
].chip
.name
= gc
->domain
->name
;
145 ct
[i
].regs
.enable
= ctl_base
+ IRQ_EN_SET
;
146 ct
[i
].regs
.disable
= ctl_base
+ IRQ_EN_CLR
;
147 ct
[i
].regs
.ack
= edge_base
+ EDGE_RAWSTAT
;
148 ct
[i
].regs
.type
= edge_base
;
151 ct
[0].type
= IRQ_TYPE_LEVEL_MASK
;
152 ct
[0].handler
= handle_level_irq
;
154 ct
[1].type
= IRQ_TYPE_EDGE_BOTH
;
155 ct
[1].handler
= handle_edge_irq
;
157 intc_writel(chip
, ct
->regs
.disable
, 0xffffffff);
158 intc_writel(chip
, ct
->regs
.ack
, 0xffffffff);
161 static void __init
tangox_irq_domain_init(struct irq_domain
*dom
)
163 struct irq_chip_generic
*gc
;
166 for (i
= 0; i
< 2; i
++) {
167 gc
= irq_get_domain_generic_chip(dom
, i
* 32);
168 tangox_irq_init_chip(gc
, i
* IRQ_CTL_HI
, i
* EDGE_CTL_HI
);
172 static int __init
tangox_irq_init(void __iomem
*base
, struct resource
*baseres
,
173 struct device_node
*node
)
175 struct tangox_irq_chip
*chip
;
176 struct irq_domain
*dom
;
181 irq
= irq_of_parse_and_map(node
, 0);
183 panic("%pOFn: failed to get IRQ", node
);
185 err
= of_address_to_resource(node
, 0, &res
);
187 panic("%pOFn: failed to get address", node
);
189 chip
= kzalloc(sizeof(*chip
), GFP_KERNEL
);
190 chip
->ctl
= res
.start
- baseres
->start
;
193 dom
= irq_domain_add_linear(node
, 64, &irq_generic_chip_ops
, chip
);
195 panic("%pOFn: failed to create irqdomain", node
);
197 err
= irq_alloc_domain_generic_chips(dom
, 32, 2, node
->name
,
198 handle_level_irq
, 0, 0, 0);
200 panic("%pOFn: failed to allocate irqchip", node
);
202 tangox_irq_domain_init(dom
);
204 irq_set_chained_handler_and_data(irq
, tangox_irq_handler
, dom
);
209 static int __init
tangox_of_irq_init(struct device_node
*node
,
210 struct device_node
*parent
)
212 struct device_node
*c
;
216 base
= of_iomap(node
, 0);
218 panic("%pOFn: of_iomap failed", node
);
220 of_address_to_resource(node
, 0, &res
);
222 for_each_child_of_node(node
, c
)
223 tangox_irq_init(base
, &res
, c
);
227 IRQCHIP_DECLARE(tangox_intc
, "sigma,smp8642-intc", tangox_of_irq_init
);