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
;
41 static int imx_irqsteer_get_reg_index(struct irqsteer_data
*data
,
44 return (data
->reg_num
- irqnum
/ 32 - 1);
47 static void imx_irqsteer_irq_unmask(struct irq_data
*d
)
49 struct irqsteer_data
*data
= d
->chip_data
;
50 int idx
= imx_irqsteer_get_reg_index(data
, d
->hwirq
);
54 raw_spin_lock_irqsave(&data
->lock
, flags
);
55 val
= readl_relaxed(data
->regs
+ CHANMASK(idx
, data
->reg_num
));
56 val
|= BIT(d
->hwirq
% 32);
57 writel_relaxed(val
, data
->regs
+ CHANMASK(idx
, data
->reg_num
));
58 raw_spin_unlock_irqrestore(&data
->lock
, flags
);
61 static void imx_irqsteer_irq_mask(struct irq_data
*d
)
63 struct irqsteer_data
*data
= d
->chip_data
;
64 int idx
= imx_irqsteer_get_reg_index(data
, d
->hwirq
);
68 raw_spin_lock_irqsave(&data
->lock
, flags
);
69 val
= readl_relaxed(data
->regs
+ CHANMASK(idx
, data
->reg_num
));
70 val
&= ~BIT(d
->hwirq
% 32);
71 writel_relaxed(val
, data
->regs
+ CHANMASK(idx
, data
->reg_num
));
72 raw_spin_unlock_irqrestore(&data
->lock
, flags
);
75 static const struct irq_chip imx_irqsteer_irq_chip
= {
77 .irq_mask
= imx_irqsteer_irq_mask
,
78 .irq_unmask
= imx_irqsteer_irq_unmask
,
81 static int imx_irqsteer_irq_map(struct irq_domain
*h
, unsigned int irq
,
82 irq_hw_number_t hwirq
)
84 irq_set_status_flags(irq
, IRQ_LEVEL
);
85 irq_set_chip_data(irq
, h
->host_data
);
86 irq_set_chip_and_handler(irq
, &imx_irqsteer_irq_chip
, handle_level_irq
);
91 static const struct irq_domain_ops imx_irqsteer_domain_ops
= {
92 .map
= imx_irqsteer_irq_map
,
93 .xlate
= irq_domain_xlate_onecell
,
96 static int imx_irqsteer_get_hwirq_base(struct irqsteer_data
*data
, u32 irq
)
100 for (i
= 0; i
< data
->irq_count
; i
++) {
101 if (data
->irq
[i
] == irq
)
108 static void imx_irqsteer_irq_handler(struct irq_desc
*desc
)
110 struct irqsteer_data
*data
= irq_desc_get_handler_data(desc
);
114 chained_irq_enter(irq_desc_get_chip(desc
), desc
);
116 irq
= irq_desc_get_irq(desc
);
117 hwirq
= imx_irqsteer_get_hwirq_base(data
, irq
);
119 pr_warn("%s: unable to get hwirq base for irq %d\n",
124 for (i
= 0; i
< 2; i
++, hwirq
+= 32) {
125 int idx
= imx_irqsteer_get_reg_index(data
, hwirq
);
126 unsigned long irqmap
;
129 if (hwirq
>= data
->reg_num
* 32)
132 irqmap
= readl_relaxed(data
->regs
+
133 CHANSTATUS(idx
, data
->reg_num
));
135 for_each_set_bit(pos
, &irqmap
, 32)
136 generic_handle_domain_irq(data
->domain
, pos
+ hwirq
);
139 chained_irq_exit(irq_desc_get_chip(desc
), desc
);
142 static int imx_irqsteer_probe(struct platform_device
*pdev
)
144 struct device_node
*np
= pdev
->dev
.of_node
;
145 struct irqsteer_data
*data
;
149 data
= devm_kzalloc(&pdev
->dev
, sizeof(*data
), GFP_KERNEL
);
153 data
->regs
= devm_platform_ioremap_resource(pdev
, 0);
154 if (IS_ERR(data
->regs
)) {
155 dev_err(&pdev
->dev
, "failed to initialize reg\n");
156 return PTR_ERR(data
->regs
);
159 data
->ipg_clk
= devm_clk_get(&pdev
->dev
, "ipg");
160 if (IS_ERR(data
->ipg_clk
))
161 return dev_err_probe(&pdev
->dev
, PTR_ERR(data
->ipg_clk
),
162 "failed to get ipg clk\n");
164 raw_spin_lock_init(&data
->lock
);
166 ret
= of_property_read_u32(np
, "fsl,num-irqs", &irqs_num
);
169 ret
= of_property_read_u32(np
, "fsl,channel", &data
->channel
);
174 * There is one output irq for each group of 64 inputs.
175 * One register bit map can represent 32 input interrupts.
177 data
->irq_count
= DIV_ROUND_UP(irqs_num
, 64);
178 data
->reg_num
= irqs_num
/ 32;
180 if (IS_ENABLED(CONFIG_PM
)) {
181 data
->saved_reg
= devm_kzalloc(&pdev
->dev
,
182 sizeof(u32
) * data
->reg_num
,
184 if (!data
->saved_reg
)
188 ret
= clk_prepare_enable(data
->ipg_clk
);
190 dev_err(&pdev
->dev
, "failed to enable ipg clk: %d\n", ret
);
194 /* steer all IRQs into configured channel */
195 writel_relaxed(BIT(data
->channel
), data
->regs
+ CHANCTRL
);
197 data
->domain
= irq_domain_add_linear(np
, data
->reg_num
* 32,
198 &imx_irqsteer_domain_ops
, data
);
200 dev_err(&pdev
->dev
, "failed to create IRQ domain\n");
204 irq_domain_set_pm_device(data
->domain
, &pdev
->dev
);
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
);
225 pm_runtime_set_active(&pdev
->dev
);
226 pm_runtime_enable(&pdev
->dev
);
230 clk_disable_unprepare(data
->ipg_clk
);
234 static void imx_irqsteer_remove(struct platform_device
*pdev
)
236 struct irqsteer_data
*irqsteer_data
= platform_get_drvdata(pdev
);
239 for (i
= 0; i
< irqsteer_data
->irq_count
; i
++)
240 irq_set_chained_handler_and_data(irqsteer_data
->irq
[i
],
243 irq_domain_remove(irqsteer_data
->domain
);
245 clk_disable_unprepare(irqsteer_data
->ipg_clk
);
249 static void imx_irqsteer_save_regs(struct irqsteer_data
*data
)
253 for (i
= 0; i
< data
->reg_num
; i
++)
254 data
->saved_reg
[i
] = readl_relaxed(data
->regs
+
255 CHANMASK(i
, data
->reg_num
));
258 static void imx_irqsteer_restore_regs(struct irqsteer_data
*data
)
262 writel_relaxed(BIT(data
->channel
), data
->regs
+ CHANCTRL
);
263 for (i
= 0; i
< data
->reg_num
; i
++)
264 writel_relaxed(data
->saved_reg
[i
],
265 data
->regs
+ CHANMASK(i
, data
->reg_num
));
268 static int imx_irqsteer_suspend(struct device
*dev
)
270 struct irqsteer_data
*irqsteer_data
= dev_get_drvdata(dev
);
272 imx_irqsteer_save_regs(irqsteer_data
);
273 clk_disable_unprepare(irqsteer_data
->ipg_clk
);
278 static int imx_irqsteer_resume(struct device
*dev
)
280 struct irqsteer_data
*irqsteer_data
= dev_get_drvdata(dev
);
283 ret
= clk_prepare_enable(irqsteer_data
->ipg_clk
);
285 dev_err(dev
, "failed to enable ipg clk: %d\n", ret
);
288 imx_irqsteer_restore_regs(irqsteer_data
);
294 static const struct dev_pm_ops imx_irqsteer_pm_ops
= {
295 SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend
,
296 pm_runtime_force_resume
)
297 SET_RUNTIME_PM_OPS(imx_irqsteer_suspend
,
298 imx_irqsteer_resume
, NULL
)
301 static const struct of_device_id imx_irqsteer_dt_ids
[] = {
302 { .compatible
= "fsl,imx-irqsteer", },
306 static struct platform_driver imx_irqsteer_driver
= {
308 .name
= "imx-irqsteer",
309 .of_match_table
= imx_irqsteer_dt_ids
,
310 .pm
= &imx_irqsteer_pm_ops
,
312 .probe
= imx_irqsteer_probe
,
313 .remove_new
= imx_irqsteer_remove
,
315 builtin_platform_driver(imx_irqsteer_driver
);