drm/nouveau: fix kernel-doc comments
[drm/drm-misc.git] / drivers / irqchip / irq-renesas-rzv2h.c
blobfe2d29e910261bf3ed05830e8ffd9fb397c62be5
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Renesas RZ/V2H(P) ICU Driver
5 * Based on irq-renesas-rzg2l.c
7 * Copyright (C) 2024 Renesas Electronics Corporation.
9 * Author: Fabrizio Castro <fabrizio.castro.jz@renesas.com>
12 #include <linux/bitfield.h>
13 #include <linux/cleanup.h>
14 #include <linux/clk.h>
15 #include <linux/err.h>
16 #include <linux/io.h>
17 #include <linux/irqchip.h>
18 #include <linux/irqdomain.h>
19 #include <linux/of_address.h>
20 #include <linux/of_platform.h>
21 #include <linux/pm_runtime.h>
22 #include <linux/reset.h>
23 #include <linux/spinlock.h>
24 #include <linux/syscore_ops.h>
26 /* DT "interrupts" indexes */
27 #define ICU_IRQ_START 1
28 #define ICU_IRQ_COUNT 16
29 #define ICU_TINT_START (ICU_IRQ_START + ICU_IRQ_COUNT)
30 #define ICU_TINT_COUNT 32
31 #define ICU_NUM_IRQ (ICU_TINT_START + ICU_TINT_COUNT)
33 /* Registers */
34 #define ICU_NSCNT 0x00
35 #define ICU_NSCLR 0x04
36 #define ICU_NITSR 0x08
37 #define ICU_ISCTR 0x10
38 #define ICU_ISCLR 0x14
39 #define ICU_IITSR 0x18
40 #define ICU_TSCTR 0x20
41 #define ICU_TSCLR 0x24
42 #define ICU_TITSR(k) (0x28 + (k) * 4)
43 #define ICU_TSSR(k) (0x30 + (k) * 4)
45 /* NMI */
46 #define ICU_NMI_EDGE_FALLING 0
47 #define ICU_NMI_EDGE_RISING 1
49 #define ICU_NSCLR_NCLR BIT(0)
51 /* IRQ */
52 #define ICU_IRQ_LEVEL_LOW 0
53 #define ICU_IRQ_EDGE_FALLING 1
54 #define ICU_IRQ_EDGE_RISING 2
55 #define ICU_IRQ_EDGE_BOTH 3
57 #define ICU_IITSR_IITSEL_PREP(iitsel, n) ((iitsel) << ((n) * 2))
58 #define ICU_IITSR_IITSEL_GET(iitsr, n) (((iitsr) >> ((n) * 2)) & 0x03)
59 #define ICU_IITSR_IITSEL_MASK(n) ICU_IITSR_IITSEL_PREP(0x03, n)
61 /* TINT */
62 #define ICU_TINT_EDGE_RISING 0
63 #define ICU_TINT_EDGE_FALLING 1
64 #define ICU_TINT_LEVEL_HIGH 2
65 #define ICU_TINT_LEVEL_LOW 3
67 #define ICU_TSSR_K(tint_nr) ((tint_nr) / 4)
68 #define ICU_TSSR_TSSEL_N(tint_nr) ((tint_nr) % 4)
69 #define ICU_TSSR_TSSEL_PREP(tssel, n) ((tssel) << ((n) * 8))
70 #define ICU_TSSR_TSSEL_MASK(n) ICU_TSSR_TSSEL_PREP(0x7F, n)
71 #define ICU_TSSR_TIEN(n) (BIT(7) << ((n) * 8))
73 #define ICU_TITSR_K(tint_nr) ((tint_nr) / 16)
74 #define ICU_TITSR_TITSEL_N(tint_nr) ((tint_nr) % 16)
75 #define ICU_TITSR_TITSEL_PREP(titsel, n) ICU_IITSR_IITSEL_PREP(titsel, n)
76 #define ICU_TITSR_TITSEL_MASK(n) ICU_IITSR_IITSEL_MASK(n)
77 #define ICU_TITSR_TITSEL_GET(titsr, n) ICU_IITSR_IITSEL_GET(titsr, n)
79 #define ICU_TINT_EXTRACT_HWIRQ(x) FIELD_GET(GENMASK(15, 0), (x))
80 #define ICU_TINT_EXTRACT_GPIOINT(x) FIELD_GET(GENMASK(31, 16), (x))
81 #define ICU_PB5_TINT 0x55
83 /**
84 * struct rzv2h_icu_priv - Interrupt Control Unit controller private data structure.
85 * @base: Controller's base address
86 * @irqchip: Pointer to struct irq_chip
87 * @fwspec: IRQ firmware specific data
88 * @lock: Lock to serialize access to hardware registers
90 struct rzv2h_icu_priv {
91 void __iomem *base;
92 const struct irq_chip *irqchip;
93 struct irq_fwspec fwspec[ICU_NUM_IRQ];
94 raw_spinlock_t lock;
97 static inline struct rzv2h_icu_priv *irq_data_to_priv(struct irq_data *data)
99 return data->domain->host_data;
102 static void rzv2h_icu_eoi(struct irq_data *d)
104 struct rzv2h_icu_priv *priv = irq_data_to_priv(d);
105 unsigned int hw_irq = irqd_to_hwirq(d);
106 unsigned int tintirq_nr;
107 u32 bit;
109 scoped_guard(raw_spinlock, &priv->lock) {
110 if (hw_irq >= ICU_TINT_START) {
111 tintirq_nr = hw_irq - ICU_TINT_START;
112 bit = BIT(tintirq_nr);
113 if (!irqd_is_level_type(d))
114 writel_relaxed(bit, priv->base + ICU_TSCLR);
115 } else if (hw_irq >= ICU_IRQ_START) {
116 tintirq_nr = hw_irq - ICU_IRQ_START;
117 bit = BIT(tintirq_nr);
118 if (!irqd_is_level_type(d))
119 writel_relaxed(bit, priv->base + ICU_ISCLR);
120 } else {
121 writel_relaxed(ICU_NSCLR_NCLR, priv->base + ICU_NSCLR);
125 irq_chip_eoi_parent(d);
128 static void rzv2h_tint_irq_endisable(struct irq_data *d, bool enable)
130 struct rzv2h_icu_priv *priv = irq_data_to_priv(d);
131 unsigned int hw_irq = irqd_to_hwirq(d);
132 u32 tint_nr, tssel_n, k, tssr;
134 if (hw_irq < ICU_TINT_START)
135 return;
137 tint_nr = hw_irq - ICU_TINT_START;
138 k = ICU_TSSR_K(tint_nr);
139 tssel_n = ICU_TSSR_TSSEL_N(tint_nr);
141 guard(raw_spinlock)(&priv->lock);
142 tssr = readl_relaxed(priv->base + ICU_TSSR(k));
143 if (enable)
144 tssr |= ICU_TSSR_TIEN(tssel_n);
145 else
146 tssr &= ~ICU_TSSR_TIEN(tssel_n);
147 writel_relaxed(tssr, priv->base + ICU_TSSR(k));
150 static void rzv2h_icu_irq_disable(struct irq_data *d)
152 irq_chip_disable_parent(d);
153 rzv2h_tint_irq_endisable(d, false);
156 static void rzv2h_icu_irq_enable(struct irq_data *d)
158 rzv2h_tint_irq_endisable(d, true);
159 irq_chip_enable_parent(d);
162 static int rzv2h_nmi_set_type(struct irq_data *d, unsigned int type)
164 struct rzv2h_icu_priv *priv = irq_data_to_priv(d);
165 u32 sense;
167 switch (type & IRQ_TYPE_SENSE_MASK) {
168 case IRQ_TYPE_EDGE_FALLING:
169 sense = ICU_NMI_EDGE_FALLING;
170 break;
172 case IRQ_TYPE_EDGE_RISING:
173 sense = ICU_NMI_EDGE_RISING;
174 break;
176 default:
177 return -EINVAL;
180 writel_relaxed(sense, priv->base + ICU_NITSR);
182 return 0;
185 static void rzv2h_clear_irq_int(struct rzv2h_icu_priv *priv, unsigned int hwirq)
187 unsigned int irq_nr = hwirq - ICU_IRQ_START;
188 u32 isctr, iitsr, iitsel;
189 u32 bit = BIT(irq_nr);
191 isctr = readl_relaxed(priv->base + ICU_ISCTR);
192 iitsr = readl_relaxed(priv->base + ICU_IITSR);
193 iitsel = ICU_IITSR_IITSEL_GET(iitsr, irq_nr);
196 * When level sensing is used, the interrupt flag gets automatically cleared when the
197 * interrupt signal is de-asserted by the source of the interrupt request, therefore clear
198 * the interrupt only for edge triggered interrupts.
200 if ((isctr & bit) && (iitsel != ICU_IRQ_LEVEL_LOW))
201 writel_relaxed(bit, priv->base + ICU_ISCLR);
204 static int rzv2h_irq_set_type(struct irq_data *d, unsigned int type)
206 struct rzv2h_icu_priv *priv = irq_data_to_priv(d);
207 unsigned int hwirq = irqd_to_hwirq(d);
208 u32 irq_nr = hwirq - ICU_IRQ_START;
209 u32 iitsr, sense;
211 switch (type & IRQ_TYPE_SENSE_MASK) {
212 case IRQ_TYPE_LEVEL_LOW:
213 sense = ICU_IRQ_LEVEL_LOW;
214 break;
216 case IRQ_TYPE_EDGE_FALLING:
217 sense = ICU_IRQ_EDGE_FALLING;
218 break;
220 case IRQ_TYPE_EDGE_RISING:
221 sense = ICU_IRQ_EDGE_RISING;
222 break;
224 case IRQ_TYPE_EDGE_BOTH:
225 sense = ICU_IRQ_EDGE_BOTH;
226 break;
228 default:
229 return -EINVAL;
232 guard(raw_spinlock)(&priv->lock);
233 iitsr = readl_relaxed(priv->base + ICU_IITSR);
234 iitsr &= ~ICU_IITSR_IITSEL_MASK(irq_nr);
235 iitsr |= ICU_IITSR_IITSEL_PREP(sense, irq_nr);
236 rzv2h_clear_irq_int(priv, hwirq);
237 writel_relaxed(iitsr, priv->base + ICU_IITSR);
239 return 0;
242 static void rzv2h_clear_tint_int(struct rzv2h_icu_priv *priv, unsigned int hwirq)
244 unsigned int tint_nr = hwirq - ICU_TINT_START;
245 int titsel_n = ICU_TITSR_TITSEL_N(tint_nr);
246 u32 tsctr, titsr, titsel;
247 u32 bit = BIT(tint_nr);
248 int k = tint_nr / 16;
250 tsctr = readl_relaxed(priv->base + ICU_TSCTR);
251 titsr = readl_relaxed(priv->base + ICU_TITSR(k));
252 titsel = ICU_TITSR_TITSEL_GET(titsr, titsel_n);
255 * Writing 1 to the corresponding flag from register ICU_TSCTR only has effect if
256 * TSTATn = 1b and if it's a rising edge or a falling edge interrupt.
258 if ((tsctr & bit) && ((titsel == ICU_TINT_EDGE_RISING) ||
259 (titsel == ICU_TINT_EDGE_FALLING)))
260 writel_relaxed(bit, priv->base + ICU_TSCLR);
263 static int rzv2h_tint_set_type(struct irq_data *d, unsigned int type)
265 u32 titsr, titsr_k, titsel_n, tien;
266 struct rzv2h_icu_priv *priv;
267 u32 tssr, tssr_k, tssel_n;
268 unsigned int hwirq;
269 u32 tint, sense;
270 int tint_nr;
272 switch (type & IRQ_TYPE_SENSE_MASK) {
273 case IRQ_TYPE_LEVEL_LOW:
274 sense = ICU_TINT_LEVEL_LOW;
275 break;
277 case IRQ_TYPE_LEVEL_HIGH:
278 sense = ICU_TINT_LEVEL_HIGH;
279 break;
281 case IRQ_TYPE_EDGE_RISING:
282 sense = ICU_TINT_EDGE_RISING;
283 break;
285 case IRQ_TYPE_EDGE_FALLING:
286 sense = ICU_TINT_EDGE_FALLING;
287 break;
289 default:
290 return -EINVAL;
293 tint = (u32)(uintptr_t)irq_data_get_irq_chip_data(d);
294 if (tint > ICU_PB5_TINT)
295 return -EINVAL;
297 priv = irq_data_to_priv(d);
298 hwirq = irqd_to_hwirq(d);
300 tint_nr = hwirq - ICU_TINT_START;
302 tssr_k = ICU_TSSR_K(tint_nr);
303 tssel_n = ICU_TSSR_TSSEL_N(tint_nr);
305 titsr_k = ICU_TITSR_K(tint_nr);
306 titsel_n = ICU_TITSR_TITSEL_N(tint_nr);
307 tien = ICU_TSSR_TIEN(titsel_n);
309 guard(raw_spinlock)(&priv->lock);
311 tssr = readl_relaxed(priv->base + ICU_TSSR(tssr_k));
312 tssr &= ~(ICU_TSSR_TSSEL_MASK(tssel_n) | tien);
313 tssr |= ICU_TSSR_TSSEL_PREP(tint, tssel_n);
315 writel_relaxed(tssr, priv->base + ICU_TSSR(tssr_k));
317 titsr = readl_relaxed(priv->base + ICU_TITSR(titsr_k));
318 titsr &= ~ICU_TITSR_TITSEL_MASK(titsel_n);
319 titsr |= ICU_TITSR_TITSEL_PREP(sense, titsel_n);
321 writel_relaxed(titsr, priv->base + ICU_TITSR(titsr_k));
323 rzv2h_clear_tint_int(priv, hwirq);
325 writel_relaxed(tssr | tien, priv->base + ICU_TSSR(tssr_k));
327 return 0;
330 static int rzv2h_icu_set_type(struct irq_data *d, unsigned int type)
332 unsigned int hw_irq = irqd_to_hwirq(d);
333 int ret;
335 if (hw_irq >= ICU_TINT_START)
336 ret = rzv2h_tint_set_type(d, type);
337 else if (hw_irq >= ICU_IRQ_START)
338 ret = rzv2h_irq_set_type(d, type);
339 else
340 ret = rzv2h_nmi_set_type(d, type);
342 if (ret)
343 return ret;
345 return irq_chip_set_type_parent(d, IRQ_TYPE_LEVEL_HIGH);
348 static const struct irq_chip rzv2h_icu_chip = {
349 .name = "rzv2h-icu",
350 .irq_eoi = rzv2h_icu_eoi,
351 .irq_mask = irq_chip_mask_parent,
352 .irq_unmask = irq_chip_unmask_parent,
353 .irq_disable = rzv2h_icu_irq_disable,
354 .irq_enable = rzv2h_icu_irq_enable,
355 .irq_get_irqchip_state = irq_chip_get_parent_state,
356 .irq_set_irqchip_state = irq_chip_set_parent_state,
357 .irq_retrigger = irq_chip_retrigger_hierarchy,
358 .irq_set_type = rzv2h_icu_set_type,
359 .irq_set_affinity = irq_chip_set_affinity_parent,
360 .flags = IRQCHIP_SET_TYPE_MASKED,
363 static int rzv2h_icu_alloc(struct irq_domain *domain, unsigned int virq, unsigned int nr_irqs,
364 void *arg)
366 struct rzv2h_icu_priv *priv = domain->host_data;
367 unsigned long tint = 0;
368 irq_hw_number_t hwirq;
369 unsigned int type;
370 int ret;
372 ret = irq_domain_translate_twocell(domain, arg, &hwirq, &type);
373 if (ret)
374 return ret;
377 * For TINT interrupts the hwirq and TINT are encoded in
378 * fwspec->param[0].
379 * hwirq is embedded in bits 0-15.
380 * TINT is embedded in bits 16-31.
382 if (hwirq >= ICU_TINT_START) {
383 tint = ICU_TINT_EXTRACT_GPIOINT(hwirq);
384 hwirq = ICU_TINT_EXTRACT_HWIRQ(hwirq);
386 if (hwirq < ICU_TINT_START)
387 return -EINVAL;
390 if (hwirq > (ICU_NUM_IRQ - 1))
391 return -EINVAL;
393 ret = irq_domain_set_hwirq_and_chip(domain, virq, hwirq, priv->irqchip,
394 (void *)(uintptr_t)tint);
395 if (ret)
396 return ret;
398 return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &priv->fwspec[hwirq]);
401 static const struct irq_domain_ops rzv2h_icu_domain_ops = {
402 .alloc = rzv2h_icu_alloc,
403 .free = irq_domain_free_irqs_common,
404 .translate = irq_domain_translate_twocell,
407 static int rzv2h_icu_parse_interrupts(struct rzv2h_icu_priv *priv, struct device_node *np)
409 struct of_phandle_args map;
410 unsigned int i;
411 int ret;
413 for (i = 0; i < ICU_NUM_IRQ; i++) {
414 ret = of_irq_parse_one(np, i, &map);
415 if (ret)
416 return ret;
418 of_phandle_args_to_fwspec(np, map.args, map.args_count, &priv->fwspec[i]);
421 return 0;
424 static int rzv2h_icu_init(struct device_node *node, struct device_node *parent)
426 struct irq_domain *irq_domain, *parent_domain;
427 struct rzv2h_icu_priv *rzv2h_icu_data;
428 struct platform_device *pdev;
429 struct reset_control *resetn;
430 int ret;
432 pdev = of_find_device_by_node(node);
433 if (!pdev)
434 return -ENODEV;
436 parent_domain = irq_find_host(parent);
437 if (!parent_domain) {
438 dev_err(&pdev->dev, "cannot find parent domain\n");
439 ret = -ENODEV;
440 goto put_dev;
443 rzv2h_icu_data = devm_kzalloc(&pdev->dev, sizeof(*rzv2h_icu_data), GFP_KERNEL);
444 if (!rzv2h_icu_data) {
445 ret = -ENOMEM;
446 goto put_dev;
449 rzv2h_icu_data->irqchip = &rzv2h_icu_chip;
451 rzv2h_icu_data->base = devm_of_iomap(&pdev->dev, pdev->dev.of_node, 0, NULL);
452 if (IS_ERR(rzv2h_icu_data->base)) {
453 ret = PTR_ERR(rzv2h_icu_data->base);
454 goto put_dev;
457 ret = rzv2h_icu_parse_interrupts(rzv2h_icu_data, node);
458 if (ret) {
459 dev_err(&pdev->dev, "cannot parse interrupts: %d\n", ret);
460 goto put_dev;
463 resetn = devm_reset_control_get_exclusive(&pdev->dev, NULL);
464 if (IS_ERR(resetn)) {
465 ret = PTR_ERR(resetn);
466 goto put_dev;
469 ret = reset_control_deassert(resetn);
470 if (ret) {
471 dev_err(&pdev->dev, "failed to deassert resetn pin, %d\n", ret);
472 goto put_dev;
475 pm_runtime_enable(&pdev->dev);
476 ret = pm_runtime_resume_and_get(&pdev->dev);
477 if (ret < 0) {
478 dev_err(&pdev->dev, "pm_runtime_resume_and_get failed: %d\n", ret);
479 goto pm_disable;
482 raw_spin_lock_init(&rzv2h_icu_data->lock);
484 irq_domain = irq_domain_add_hierarchy(parent_domain, 0, ICU_NUM_IRQ, node,
485 &rzv2h_icu_domain_ops, rzv2h_icu_data);
486 if (!irq_domain) {
487 dev_err(&pdev->dev, "failed to add irq domain\n");
488 ret = -ENOMEM;
489 goto pm_put;
493 * coccicheck complains about a missing put_device call before returning, but it's a false
494 * positive. We still need &pdev->dev after successfully returning from this function.
496 return 0;
498 pm_put:
499 pm_runtime_put(&pdev->dev);
500 pm_disable:
501 pm_runtime_disable(&pdev->dev);
502 reset_control_assert(resetn);
503 put_dev:
504 put_device(&pdev->dev);
506 return ret;
509 IRQCHIP_PLATFORM_DRIVER_BEGIN(rzv2h_icu)
510 IRQCHIP_MATCH("renesas,r9a09g057-icu", rzv2h_icu_init)
511 IRQCHIP_PLATFORM_DRIVER_END(rzv2h_icu)
512 MODULE_AUTHOR("Fabrizio Castro <fabrizio.castro.jz@renesas.com>");
513 MODULE_DESCRIPTION("Renesas RZ/V2H(P) ICU Driver");