1 // SPDX-License-Identifier: GPL-2.0+
4 * Copyright (C) 2018 Pengutronix, Lucas Stach <kernel@pengutronix.de>
8 #include <linux/interrupt.h>
10 #include <linux/irqchip/chained_irq.h>
11 #include <linux/irqdomain.h>
12 #include <linux/kernel.h>
13 #include <linux/of_irq.h>
14 #include <linux/of_platform.h>
15 #include <linux/spinlock.h>
17 #define CTRL_STRIDE_OFF(_t, _r) (_t * 4 * _r)
19 #define CHANMASK(n, t) (CTRL_STRIDE_OFF(t, 0) + 0x4 * (n) + 0x4)
20 #define CHANSET(n, t) (CTRL_STRIDE_OFF(t, 1) + 0x4 * (n) + 0x4)
21 #define CHANSTATUS(n, t) (CTRL_STRIDE_OFF(t, 2) + 0x4 * (n) + 0x4)
22 #define CHAN_MINTDIS(t) (CTRL_STRIDE_OFF(t, 3) + 0x4)
23 #define CHAN_MASTRSTAT(t) (CTRL_STRIDE_OFF(t, 3) + 0x8)
25 #define CHAN_MAX_OUTPUT_INT 0x8
27 struct irqsteer_data
{
30 int irq
[CHAN_MAX_OUTPUT_INT
];
35 struct irq_domain
*domain
;
39 static int imx_irqsteer_get_reg_index(struct irqsteer_data
*data
,
42 return (data
->reg_num
- irqnum
/ 32 - 1);
45 static void imx_irqsteer_irq_unmask(struct irq_data
*d
)
47 struct irqsteer_data
*data
= d
->chip_data
;
48 int idx
= imx_irqsteer_get_reg_index(data
, d
->hwirq
);
52 raw_spin_lock_irqsave(&data
->lock
, flags
);
53 val
= readl_relaxed(data
->regs
+ CHANMASK(idx
, data
->reg_num
));
54 val
|= BIT(d
->hwirq
% 32);
55 writel_relaxed(val
, data
->regs
+ CHANMASK(idx
, data
->reg_num
));
56 raw_spin_unlock_irqrestore(&data
->lock
, flags
);
59 static void imx_irqsteer_irq_mask(struct irq_data
*d
)
61 struct irqsteer_data
*data
= d
->chip_data
;
62 int idx
= imx_irqsteer_get_reg_index(data
, d
->hwirq
);
66 raw_spin_lock_irqsave(&data
->lock
, flags
);
67 val
= readl_relaxed(data
->regs
+ CHANMASK(idx
, data
->reg_num
));
68 val
&= ~BIT(d
->hwirq
% 32);
69 writel_relaxed(val
, data
->regs
+ CHANMASK(idx
, data
->reg_num
));
70 raw_spin_unlock_irqrestore(&data
->lock
, flags
);
73 static struct irq_chip imx_irqsteer_irq_chip
= {
75 .irq_mask
= imx_irqsteer_irq_mask
,
76 .irq_unmask
= imx_irqsteer_irq_unmask
,
79 static int imx_irqsteer_irq_map(struct irq_domain
*h
, unsigned int irq
,
80 irq_hw_number_t hwirq
)
82 irq_set_status_flags(irq
, IRQ_LEVEL
);
83 irq_set_chip_data(irq
, h
->host_data
);
84 irq_set_chip_and_handler(irq
, &imx_irqsteer_irq_chip
, handle_level_irq
);
89 static const struct irq_domain_ops imx_irqsteer_domain_ops
= {
90 .map
= imx_irqsteer_irq_map
,
91 .xlate
= irq_domain_xlate_onecell
,
94 static int imx_irqsteer_get_hwirq_base(struct irqsteer_data
*data
, u32 irq
)
98 for (i
= 0; i
< data
->irq_count
; i
++) {
99 if (data
->irq
[i
] == irq
)
106 static void imx_irqsteer_irq_handler(struct irq_desc
*desc
)
108 struct irqsteer_data
*data
= irq_desc_get_handler_data(desc
);
112 chained_irq_enter(irq_desc_get_chip(desc
), desc
);
114 irq
= irq_desc_get_irq(desc
);
115 hwirq
= imx_irqsteer_get_hwirq_base(data
, irq
);
117 pr_warn("%s: unable to get hwirq base for irq %d\n",
122 for (i
= 0; i
< 2; i
++, hwirq
+= 32) {
123 int idx
= imx_irqsteer_get_reg_index(data
, hwirq
);
124 unsigned long irqmap
;
127 if (hwirq
>= data
->reg_num
* 32)
130 irqmap
= readl_relaxed(data
->regs
+
131 CHANSTATUS(idx
, data
->reg_num
));
133 for_each_set_bit(pos
, &irqmap
, 32) {
134 virq
= irq_find_mapping(data
->domain
, pos
+ hwirq
);
136 generic_handle_irq(virq
);
140 chained_irq_exit(irq_desc_get_chip(desc
), desc
);
143 static int imx_irqsteer_probe(struct platform_device
*pdev
)
145 struct device_node
*np
= pdev
->dev
.of_node
;
146 struct irqsteer_data
*data
;
150 data
= devm_kzalloc(&pdev
->dev
, sizeof(*data
), GFP_KERNEL
);
154 data
->regs
= devm_platform_ioremap_resource(pdev
, 0);
155 if (IS_ERR(data
->regs
)) {
156 dev_err(&pdev
->dev
, "failed to initialize reg\n");
157 return PTR_ERR(data
->regs
);
160 data
->ipg_clk
= devm_clk_get(&pdev
->dev
, "ipg");
161 if (IS_ERR(data
->ipg_clk
))
162 return dev_err_probe(&pdev
->dev
, PTR_ERR(data
->ipg_clk
),
163 "failed to get ipg clk\n");
165 raw_spin_lock_init(&data
->lock
);
167 ret
= of_property_read_u32(np
, "fsl,num-irqs", &irqs_num
);
170 ret
= of_property_read_u32(np
, "fsl,channel", &data
->channel
);
175 * There is one output irq for each group of 64 inputs.
176 * One register bit map can represent 32 input interrupts.
178 data
->irq_count
= DIV_ROUND_UP(irqs_num
, 64);
179 data
->reg_num
= irqs_num
/ 32;
181 if (IS_ENABLED(CONFIG_PM_SLEEP
)) {
182 data
->saved_reg
= devm_kzalloc(&pdev
->dev
,
183 sizeof(u32
) * data
->reg_num
,
185 if (!data
->saved_reg
)
189 ret
= clk_prepare_enable(data
->ipg_clk
);
191 dev_err(&pdev
->dev
, "failed to enable ipg clk: %d\n", ret
);
195 /* steer all IRQs into configured channel */
196 writel_relaxed(BIT(data
->channel
), data
->regs
+ CHANCTRL
);
198 data
->domain
= irq_domain_add_linear(np
, data
->reg_num
* 32,
199 &imx_irqsteer_domain_ops
, data
);
201 dev_err(&pdev
->dev
, "failed to create IRQ domain\n");
206 if (!data
->irq_count
|| data
->irq_count
> CHAN_MAX_OUTPUT_INT
) {
211 for (i
= 0; i
< data
->irq_count
; i
++) {
212 data
->irq
[i
] = irq_of_parse_and_map(np
, i
);
218 irq_set_chained_handler_and_data(data
->irq
[i
],
219 imx_irqsteer_irq_handler
,
223 platform_set_drvdata(pdev
, data
);
227 clk_disable_unprepare(data
->ipg_clk
);
231 static int imx_irqsteer_remove(struct platform_device
*pdev
)
233 struct irqsteer_data
*irqsteer_data
= platform_get_drvdata(pdev
);
236 for (i
= 0; i
< irqsteer_data
->irq_count
; i
++)
237 irq_set_chained_handler_and_data(irqsteer_data
->irq
[i
],
240 irq_domain_remove(irqsteer_data
->domain
);
242 clk_disable_unprepare(irqsteer_data
->ipg_clk
);
247 #ifdef CONFIG_PM_SLEEP
248 static void imx_irqsteer_save_regs(struct irqsteer_data
*data
)
252 for (i
= 0; i
< data
->reg_num
; i
++)
253 data
->saved_reg
[i
] = readl_relaxed(data
->regs
+
254 CHANMASK(i
, data
->reg_num
));
257 static void imx_irqsteer_restore_regs(struct irqsteer_data
*data
)
261 writel_relaxed(BIT(data
->channel
), data
->regs
+ CHANCTRL
);
262 for (i
= 0; i
< data
->reg_num
; i
++)
263 writel_relaxed(data
->saved_reg
[i
],
264 data
->regs
+ CHANMASK(i
, data
->reg_num
));
267 static int imx_irqsteer_suspend(struct device
*dev
)
269 struct irqsteer_data
*irqsteer_data
= dev_get_drvdata(dev
);
271 imx_irqsteer_save_regs(irqsteer_data
);
272 clk_disable_unprepare(irqsteer_data
->ipg_clk
);
277 static int imx_irqsteer_resume(struct device
*dev
)
279 struct irqsteer_data
*irqsteer_data
= dev_get_drvdata(dev
);
282 ret
= clk_prepare_enable(irqsteer_data
->ipg_clk
);
284 dev_err(dev
, "failed to enable ipg clk: %d\n", ret
);
287 imx_irqsteer_restore_regs(irqsteer_data
);
293 static const struct dev_pm_ops imx_irqsteer_pm_ops
= {
294 SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(imx_irqsteer_suspend
, imx_irqsteer_resume
)
297 static const struct of_device_id imx_irqsteer_dt_ids
[] = {
298 { .compatible
= "fsl,imx-irqsteer", },
302 static struct platform_driver imx_irqsteer_driver
= {
304 .name
= "imx-irqsteer",
305 .of_match_table
= imx_irqsteer_dt_ids
,
306 .pm
= &imx_irqsteer_pm_ops
,
308 .probe
= imx_irqsteer_probe
,
309 .remove
= imx_irqsteer_remove
,
311 builtin_platform_driver(imx_irqsteer_driver
);