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>
14 #include <linux/of_irq.h>
15 #include <linux/platform_device.h>
16 #include <linux/pm_runtime.h>
17 #include <linux/spinlock.h>
19 #define CTRL_STRIDE_OFF(_t, _r) (_t * 4 * _r)
21 #define CHANMASK(n, t) (CTRL_STRIDE_OFF(t, 0) + 0x4 * (n) + 0x4)
22 #define CHANSET(n, t) (CTRL_STRIDE_OFF(t, 1) + 0x4 * (n) + 0x4)
23 #define CHANSTATUS(n, t) (CTRL_STRIDE_OFF(t, 2) + 0x4 * (n) + 0x4)
24 #define CHAN_MINTDIS(t) (CTRL_STRIDE_OFF(t, 3) + 0x4)
25 #define CHAN_MASTRSTAT(t) (CTRL_STRIDE_OFF(t, 3) + 0x8)
27 #define CHAN_MAX_OUTPUT_INT 0x8
29 struct irqsteer_data
{
32 int irq
[CHAN_MAX_OUTPUT_INT
];
37 struct irq_domain
*domain
;
42 static int imx_irqsteer_get_reg_index(struct irqsteer_data
*data
,
45 return (data
->reg_num
- irqnum
/ 32 - 1);
48 static void imx_irqsteer_irq_unmask(struct irq_data
*d
)
50 struct irqsteer_data
*data
= d
->chip_data
;
51 int idx
= imx_irqsteer_get_reg_index(data
, d
->hwirq
);
55 raw_spin_lock_irqsave(&data
->lock
, flags
);
56 val
= readl_relaxed(data
->regs
+ CHANMASK(idx
, data
->reg_num
));
57 val
|= BIT(d
->hwirq
% 32);
58 writel_relaxed(val
, data
->regs
+ CHANMASK(idx
, data
->reg_num
));
59 raw_spin_unlock_irqrestore(&data
->lock
, flags
);
62 static void imx_irqsteer_irq_mask(struct irq_data
*d
)
64 struct irqsteer_data
*data
= d
->chip_data
;
65 int idx
= imx_irqsteer_get_reg_index(data
, d
->hwirq
);
69 raw_spin_lock_irqsave(&data
->lock
, flags
);
70 val
= readl_relaxed(data
->regs
+ CHANMASK(idx
, data
->reg_num
));
71 val
&= ~BIT(d
->hwirq
% 32);
72 writel_relaxed(val
, data
->regs
+ CHANMASK(idx
, data
->reg_num
));
73 raw_spin_unlock_irqrestore(&data
->lock
, flags
);
76 static void imx_irqsteer_irq_bus_lock(struct irq_data
*d
)
78 struct irqsteer_data
*data
= d
->chip_data
;
80 pm_runtime_get_sync(data
->dev
);
83 static void imx_irqsteer_irq_bus_sync_unlock(struct irq_data
*d
)
85 struct irqsteer_data
*data
= d
->chip_data
;
87 pm_runtime_put_autosuspend(data
->dev
);
90 static const struct irq_chip imx_irqsteer_irq_chip
= {
92 .irq_mask
= imx_irqsteer_irq_mask
,
93 .irq_unmask
= imx_irqsteer_irq_unmask
,
94 .irq_bus_lock
= imx_irqsteer_irq_bus_lock
,
95 .irq_bus_sync_unlock
= imx_irqsteer_irq_bus_sync_unlock
,
98 static int imx_irqsteer_irq_map(struct irq_domain
*h
, unsigned int irq
,
99 irq_hw_number_t hwirq
)
101 irq_set_status_flags(irq
, IRQ_LEVEL
);
102 irq_set_chip_data(irq
, h
->host_data
);
103 irq_set_chip_and_handler(irq
, &imx_irqsteer_irq_chip
, handle_level_irq
);
108 static const struct irq_domain_ops imx_irqsteer_domain_ops
= {
109 .map
= imx_irqsteer_irq_map
,
110 .xlate
= irq_domain_xlate_onecell
,
113 static int imx_irqsteer_get_hwirq_base(struct irqsteer_data
*data
, u32 irq
)
117 for (i
= 0; i
< data
->irq_count
; i
++) {
118 if (data
->irq
[i
] == irq
)
125 static void imx_irqsteer_irq_handler(struct irq_desc
*desc
)
127 struct irqsteer_data
*data
= irq_desc_get_handler_data(desc
);
131 chained_irq_enter(irq_desc_get_chip(desc
), desc
);
133 irq
= irq_desc_get_irq(desc
);
134 hwirq
= imx_irqsteer_get_hwirq_base(data
, irq
);
136 pr_warn("%s: unable to get hwirq base for irq %d\n",
141 for (i
= 0; i
< 2; i
++, hwirq
+= 32) {
142 int idx
= imx_irqsteer_get_reg_index(data
, hwirq
);
143 unsigned long irqmap
;
146 if (hwirq
>= data
->reg_num
* 32)
149 irqmap
= readl_relaxed(data
->regs
+
150 CHANSTATUS(idx
, data
->reg_num
));
152 for_each_set_bit(pos
, &irqmap
, 32)
153 generic_handle_domain_irq(data
->domain
, pos
+ hwirq
);
156 chained_irq_exit(irq_desc_get_chip(desc
), desc
);
159 static int imx_irqsteer_probe(struct platform_device
*pdev
)
161 struct device_node
*np
= pdev
->dev
.of_node
;
162 struct irqsteer_data
*data
;
166 data
= devm_kzalloc(&pdev
->dev
, sizeof(*data
), GFP_KERNEL
);
170 data
->dev
= &pdev
->dev
;
171 data
->regs
= devm_platform_ioremap_resource(pdev
, 0);
172 if (IS_ERR(data
->regs
)) {
173 dev_err(&pdev
->dev
, "failed to initialize reg\n");
174 return PTR_ERR(data
->regs
);
177 data
->ipg_clk
= devm_clk_get(&pdev
->dev
, "ipg");
178 if (IS_ERR(data
->ipg_clk
))
179 return dev_err_probe(&pdev
->dev
, PTR_ERR(data
->ipg_clk
),
180 "failed to get ipg clk\n");
182 raw_spin_lock_init(&data
->lock
);
184 ret
= of_property_read_u32(np
, "fsl,num-irqs", &irqs_num
);
187 ret
= of_property_read_u32(np
, "fsl,channel", &data
->channel
);
192 * There is one output irq for each group of 64 inputs.
193 * One register bit map can represent 32 input interrupts.
195 data
->irq_count
= DIV_ROUND_UP(irqs_num
, 64);
196 data
->reg_num
= irqs_num
/ 32;
198 if (IS_ENABLED(CONFIG_PM
)) {
199 data
->saved_reg
= devm_kzalloc(&pdev
->dev
,
200 sizeof(u32
) * data
->reg_num
,
202 if (!data
->saved_reg
)
206 ret
= clk_prepare_enable(data
->ipg_clk
);
208 dev_err(&pdev
->dev
, "failed to enable ipg clk: %d\n", ret
);
212 /* steer all IRQs into configured channel */
213 writel_relaxed(BIT(data
->channel
), data
->regs
+ CHANCTRL
);
215 data
->domain
= irq_domain_add_linear(np
, data
->reg_num
* 32,
216 &imx_irqsteer_domain_ops
, data
);
218 dev_err(&pdev
->dev
, "failed to create IRQ domain\n");
222 irq_domain_set_pm_device(data
->domain
, &pdev
->dev
);
224 if (!data
->irq_count
|| data
->irq_count
> CHAN_MAX_OUTPUT_INT
) {
229 for (i
= 0; i
< data
->irq_count
; i
++) {
230 data
->irq
[i
] = irq_of_parse_and_map(np
, i
);
236 irq_set_chained_handler_and_data(data
->irq
[i
],
237 imx_irqsteer_irq_handler
,
241 platform_set_drvdata(pdev
, data
);
243 pm_runtime_set_active(&pdev
->dev
);
244 pm_runtime_enable(&pdev
->dev
);
248 clk_disable_unprepare(data
->ipg_clk
);
252 static void imx_irqsteer_remove(struct platform_device
*pdev
)
254 struct irqsteer_data
*irqsteer_data
= platform_get_drvdata(pdev
);
257 for (i
= 0; i
< irqsteer_data
->irq_count
; i
++)
258 irq_set_chained_handler_and_data(irqsteer_data
->irq
[i
],
261 irq_domain_remove(irqsteer_data
->domain
);
263 clk_disable_unprepare(irqsteer_data
->ipg_clk
);
267 static void imx_irqsteer_save_regs(struct irqsteer_data
*data
)
271 for (i
= 0; i
< data
->reg_num
; i
++)
272 data
->saved_reg
[i
] = readl_relaxed(data
->regs
+
273 CHANMASK(i
, data
->reg_num
));
276 static void imx_irqsteer_restore_regs(struct irqsteer_data
*data
)
280 writel_relaxed(BIT(data
->channel
), data
->regs
+ CHANCTRL
);
281 for (i
= 0; i
< data
->reg_num
; i
++)
282 writel_relaxed(data
->saved_reg
[i
],
283 data
->regs
+ CHANMASK(i
, data
->reg_num
));
286 static int imx_irqsteer_suspend(struct device
*dev
)
288 struct irqsteer_data
*irqsteer_data
= dev_get_drvdata(dev
);
290 imx_irqsteer_save_regs(irqsteer_data
);
291 clk_disable_unprepare(irqsteer_data
->ipg_clk
);
296 static int imx_irqsteer_resume(struct device
*dev
)
298 struct irqsteer_data
*irqsteer_data
= dev_get_drvdata(dev
);
301 ret
= clk_prepare_enable(irqsteer_data
->ipg_clk
);
303 dev_err(dev
, "failed to enable ipg clk: %d\n", ret
);
306 imx_irqsteer_restore_regs(irqsteer_data
);
312 static const struct dev_pm_ops imx_irqsteer_pm_ops
= {
313 SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend
,
314 pm_runtime_force_resume
)
315 SET_RUNTIME_PM_OPS(imx_irqsteer_suspend
,
316 imx_irqsteer_resume
, NULL
)
319 static const struct of_device_id imx_irqsteer_dt_ids
[] = {
320 { .compatible
= "fsl,imx-irqsteer", },
324 static struct platform_driver imx_irqsteer_driver
= {
326 .name
= "imx-irqsteer",
327 .of_match_table
= imx_irqsteer_dt_ids
,
328 .pm
= &imx_irqsteer_pm_ops
,
330 .probe
= imx_irqsteer_probe
,
331 .remove
= imx_irqsteer_remove
,
333 builtin_platform_driver(imx_irqsteer_driver
);