2 * Texas Instruments Keystone IRQ controller IP driver
4 * Copyright (C) 2014 Texas Instruments, Inc.
5 * Author: Sajesh Kumar Saran <sajesh@ti.com>
6 * Grygorii Strashko <grygorii.strashko@ti.com>
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation version 2.
12 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
13 * kind, whether express or implied; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
18 #include <linux/irq.h>
19 #include <linux/bitops.h>
20 #include <linux/module.h>
21 #include <linux/moduleparam.h>
22 #include <linux/irqdomain.h>
23 #include <linux/irqchip.h>
24 #include <linux/irqchip/chained_irq.h>
26 #include <linux/of_platform.h>
27 #include <linux/mfd/syscon.h>
28 #include <linux/regmap.h>
30 /* The source ID bits start from 4 to 31 (total 28 bits)*/
32 #define KEYSTONE_N_IRQ (32 - BIT_OFS)
34 struct keystone_irq_device
{
39 struct irq_domain
*irqd
;
40 struct regmap
*devctrl_regs
;
44 static inline u32
keystone_irq_readl(struct keystone_irq_device
*kirq
)
49 ret
= regmap_read(kirq
->devctrl_regs
, kirq
->devctrl_offset
, &val
);
51 dev_dbg(kirq
->dev
, "irq read failed ret(%d)\n", ret
);
56 keystone_irq_writel(struct keystone_irq_device
*kirq
, u32 value
)
60 ret
= regmap_write(kirq
->devctrl_regs
, kirq
->devctrl_offset
, value
);
62 dev_dbg(kirq
->dev
, "irq write failed ret(%d)\n", ret
);
65 static void keystone_irq_setmask(struct irq_data
*d
)
67 struct keystone_irq_device
*kirq
= irq_data_get_irq_chip_data(d
);
69 kirq
->mask
|= BIT(d
->hwirq
);
70 dev_dbg(kirq
->dev
, "mask %lu [%x]\n", d
->hwirq
, kirq
->mask
);
73 static void keystone_irq_unmask(struct irq_data
*d
)
75 struct keystone_irq_device
*kirq
= irq_data_get_irq_chip_data(d
);
77 kirq
->mask
&= ~BIT(d
->hwirq
);
78 dev_dbg(kirq
->dev
, "unmask %lu [%x]\n", d
->hwirq
, kirq
->mask
);
81 static void keystone_irq_ack(struct irq_data
*d
)
83 /* nothing to do here */
86 static void keystone_irq_handler(unsigned irq
, struct irq_desc
*desc
)
88 struct keystone_irq_device
*kirq
= irq_desc_get_handler_data(desc
);
89 unsigned long pending
;
92 dev_dbg(kirq
->dev
, "start irq %d\n", irq
);
94 chained_irq_enter(irq_desc_get_chip(desc
), desc
);
96 pending
= keystone_irq_readl(kirq
);
97 keystone_irq_writel(kirq
, pending
);
99 dev_dbg(kirq
->dev
, "pending 0x%lx, mask 0x%x\n", pending
, kirq
->mask
);
101 pending
= (pending
>> BIT_OFS
) & ~kirq
->mask
;
103 dev_dbg(kirq
->dev
, "pending after mask 0x%lx\n", pending
);
105 for (src
= 0; src
< KEYSTONE_N_IRQ
; src
++) {
106 if (BIT(src
) & pending
) {
107 virq
= irq_find_mapping(kirq
->irqd
, src
);
108 dev_dbg(kirq
->dev
, "dispatch bit %d, virq %d\n",
111 dev_warn(kirq
->dev
, "sporious irq detected hwirq %d, virq %d\n",
113 generic_handle_irq(virq
);
117 chained_irq_exit(irq_desc_get_chip(desc
), desc
);
119 dev_dbg(kirq
->dev
, "end irq %d\n", irq
);
122 static int keystone_irq_map(struct irq_domain
*h
, unsigned int virq
,
125 struct keystone_irq_device
*kirq
= h
->host_data
;
127 irq_set_chip_data(virq
, kirq
);
128 irq_set_chip_and_handler(virq
, &kirq
->chip
, handle_level_irq
);
129 set_irq_flags(virq
, IRQF_VALID
| IRQF_PROBE
);
133 static const struct irq_domain_ops keystone_irq_ops
= {
134 .map
= keystone_irq_map
,
135 .xlate
= irq_domain_xlate_onecell
,
138 static int keystone_irq_probe(struct platform_device
*pdev
)
140 struct device
*dev
= &pdev
->dev
;
141 struct device_node
*np
= dev
->of_node
;
142 struct keystone_irq_device
*kirq
;
148 kirq
= devm_kzalloc(dev
, sizeof(*kirq
), GFP_KERNEL
);
153 syscon_regmap_lookup_by_phandle(np
, "ti,syscon-dev");
154 if (IS_ERR(kirq
->devctrl_regs
))
155 return PTR_ERR(kirq
->devctrl_regs
);
157 ret
= of_property_read_u32_index(np
, "ti,syscon-dev", 1,
158 &kirq
->devctrl_offset
);
160 dev_err(dev
, "couldn't read the devctrl_offset offset!\n");
164 kirq
->irq
= platform_get_irq(pdev
, 0);
166 dev_err(dev
, "no irq resource %d\n", kirq
->irq
);
172 kirq
->chip
.name
= "keystone-irq";
173 kirq
->chip
.irq_ack
= keystone_irq_ack
;
174 kirq
->chip
.irq_mask
= keystone_irq_setmask
;
175 kirq
->chip
.irq_unmask
= keystone_irq_unmask
;
177 kirq
->irqd
= irq_domain_add_linear(np
, KEYSTONE_N_IRQ
,
178 &keystone_irq_ops
, kirq
);
180 dev_err(dev
, "IRQ domain registration failed\n");
184 platform_set_drvdata(pdev
, kirq
);
186 irq_set_chained_handler_and_data(kirq
->irq
, keystone_irq_handler
, kirq
);
188 /* clear all source bits */
189 keystone_irq_writel(kirq
, ~0x0);
191 dev_info(dev
, "irqchip registered, nr_irqs %u\n", KEYSTONE_N_IRQ
);
196 static int keystone_irq_remove(struct platform_device
*pdev
)
198 struct keystone_irq_device
*kirq
= platform_get_drvdata(pdev
);
201 for (hwirq
= 0; hwirq
< KEYSTONE_N_IRQ
; hwirq
++)
202 irq_dispose_mapping(irq_find_mapping(kirq
->irqd
, hwirq
));
204 irq_domain_remove(kirq
->irqd
);
208 static const struct of_device_id keystone_irq_dt_ids
[] = {
209 { .compatible
= "ti,keystone-irq", },
212 MODULE_DEVICE_TABLE(of
, keystone_irq_dt_ids
);
214 static struct platform_driver keystone_irq_device_driver
= {
215 .probe
= keystone_irq_probe
,
216 .remove
= keystone_irq_remove
,
218 .name
= "keystone_irq",
219 .of_match_table
= of_match_ptr(keystone_irq_dt_ids
),
223 module_platform_driver(keystone_irq_device_driver
);
225 MODULE_AUTHOR("Texas Instruments");
226 MODULE_AUTHOR("Sajesh Kumar Saran");
227 MODULE_AUTHOR("Grygorii Strashko");
228 MODULE_DESCRIPTION("Keystone IRQ chip");
229 MODULE_LICENSE("GPL v2");