xref: /linux/drivers/irqchip/irq-renesas-rzv2h.c (revision bfdf35c5dc6267f70f76abddfacface4dd3b9ac0)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Renesas RZ/V2H(P) ICU Driver
4  *
5  * Based on irq-renesas-rzg2l.c
6  *
7  * Copyright (C) 2024 Renesas Electronics Corporation.
8  *
9  * Author: Fabrizio Castro <fabrizio.castro.jz@renesas.com>
10  */
11 
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/irqchip/irq-renesas-rzv2h.h>
19 #include <linux/irqdomain.h>
20 #include <linux/of_address.h>
21 #include <linux/of_platform.h>
22 #include <linux/pm_runtime.h>
23 #include <linux/reset.h>
24 #include <linux/spinlock.h>
25 #include <linux/syscore_ops.h>
26 
27 /* DT "interrupts" indexes */
28 #define ICU_IRQ_START				1
29 #define ICU_IRQ_COUNT				16
30 #define ICU_TINT_START				(ICU_IRQ_START + ICU_IRQ_COUNT)
31 #define ICU_TINT_COUNT				32
32 #define ICU_NUM_IRQ				(ICU_TINT_START + ICU_TINT_COUNT)
33 
34 /* Registers */
35 #define ICU_NSCNT				0x00
36 #define ICU_NSCLR				0x04
37 #define ICU_NITSR				0x08
38 #define ICU_ISCTR				0x10
39 #define ICU_ISCLR				0x14
40 #define ICU_IITSR				0x18
41 #define ICU_TSCTR				0x20
42 #define ICU_TSCLR				0x24
43 #define ICU_TITSR(k)				(0x28 + (k) * 4)
44 #define ICU_TSSR(k)				(0x30 + (k) * 4)
45 #define ICU_DMkSELy(k, y)			(0x420 + (k) * 0x20 + (y) * 4)
46 #define ICU_DMACKSELk(k)			(0x500 + (k) * 4)
47 
48 /* NMI */
49 #define ICU_NMI_EDGE_FALLING			0
50 #define ICU_NMI_EDGE_RISING			1
51 
52 #define ICU_NSCLR_NCLR				BIT(0)
53 
54 /* IRQ */
55 #define ICU_IRQ_LEVEL_LOW			0
56 #define ICU_IRQ_EDGE_FALLING			1
57 #define ICU_IRQ_EDGE_RISING			2
58 #define ICU_IRQ_EDGE_BOTH			3
59 
60 #define ICU_IITSR_IITSEL_PREP(iitsel, n)	((iitsel) << ((n) * 2))
61 #define ICU_IITSR_IITSEL_GET(iitsr, n)		(((iitsr) >> ((n) * 2)) & 0x03)
62 #define ICU_IITSR_IITSEL_MASK(n)		ICU_IITSR_IITSEL_PREP(0x03, n)
63 
64 /* TINT */
65 #define ICU_TINT_EDGE_RISING			0
66 #define ICU_TINT_EDGE_FALLING			1
67 #define ICU_TINT_LEVEL_HIGH			2
68 #define ICU_TINT_LEVEL_LOW			3
69 
70 #define ICU_TSSR_TSSEL_PREP(tssel, n, field_width)	((tssel) << ((n) * (field_width)))
71 #define ICU_TSSR_TSSEL_MASK(n, field_width)	\
72 ({\
73 		typeof(field_width) (_field_width) = (field_width); \
74 		ICU_TSSR_TSSEL_PREP((GENMASK(((_field_width) - 2), 0)), (n), _field_width); \
75 })
76 
77 #define ICU_TSSR_TIEN(n, field_width)	\
78 ({\
79 		typeof(field_width) (_field_width) = (field_width); \
80 		BIT((_field_width) - 1) << ((n) * (_field_width)); \
81 })
82 
83 #define ICU_TITSR_K(tint_nr)			((tint_nr) / 16)
84 #define ICU_TITSR_TITSEL_N(tint_nr)		((tint_nr) % 16)
85 #define ICU_TITSR_TITSEL_PREP(titsel, n)	ICU_IITSR_IITSEL_PREP(titsel, n)
86 #define ICU_TITSR_TITSEL_MASK(n)		ICU_IITSR_IITSEL_MASK(n)
87 #define ICU_TITSR_TITSEL_GET(titsr, n)		ICU_IITSR_IITSEL_GET(titsr, n)
88 
89 #define ICU_TINT_EXTRACT_HWIRQ(x)		FIELD_GET(GENMASK(15, 0), (x))
90 #define ICU_TINT_EXTRACT_GPIOINT(x)		FIELD_GET(GENMASK(31, 16), (x))
91 #define ICU_RZG3E_TINT_OFFSET			0x800
92 #define ICU_RZG3E_TSSEL_MAX_VAL			0x8c
93 #define ICU_RZV2H_TSSEL_MAX_VAL			0x55
94 
95 /**
96  * struct rzv2h_hw_info - Interrupt Control Unit controller hardware info structure.
97  * @tssel_lut:		TINT lookup table
98  * @t_offs:		TINT offset
99  * @max_tssel:		TSSEL max value
100  * @field_width:	TSSR field width
101  */
102 struct rzv2h_hw_info {
103 	const u8	*tssel_lut;
104 	u16		t_offs;
105 	u8		max_tssel;
106 	u8		field_width;
107 };
108 
109 /* DMAC */
110 #define ICU_DMAC_DkRQ_SEL_MASK			GENMASK(9, 0)
111 
112 #define ICU_DMAC_DMAREQ_SHIFT(up)		((up) * 16)
113 #define ICU_DMAC_DMAREQ_MASK(up)		(ICU_DMAC_DkRQ_SEL_MASK \
114 						 << ICU_DMAC_DMAREQ_SHIFT(up))
115 #define ICU_DMAC_PREP_DMAREQ(sel, up)		(FIELD_PREP(ICU_DMAC_DkRQ_SEL_MASK, (sel)) \
116 						 << ICU_DMAC_DMAREQ_SHIFT(up))
117 
118 /**
119  * struct rzv2h_icu_priv - Interrupt Control Unit controller private data structure.
120  * @base:	Controller's base address
121  * @fwspec:	IRQ firmware specific data
122  * @lock:	Lock to serialize access to hardware registers
123  * @info:	Pointer to struct rzv2h_hw_info
124  */
125 struct rzv2h_icu_priv {
126 	void __iomem			*base;
127 	struct irq_fwspec		fwspec[ICU_NUM_IRQ];
128 	raw_spinlock_t			lock;
129 	const struct rzv2h_hw_info	*info;
130 };
131 
rzv2h_icu_register_dma_req(struct platform_device * icu_dev,u8 dmac_index,u8 dmac_channel,u16 req_no)132 void rzv2h_icu_register_dma_req(struct platform_device *icu_dev, u8 dmac_index, u8 dmac_channel,
133 				u16 req_no)
134 {
135 	struct rzv2h_icu_priv *priv = platform_get_drvdata(icu_dev);
136 	u32 icu_dmksely, dmareq, dmareq_mask;
137 	u8 y, upper;
138 
139 	y = dmac_channel / 2;
140 	upper = dmac_channel % 2;
141 
142 	dmareq = ICU_DMAC_PREP_DMAREQ(req_no, upper);
143 	dmareq_mask = ICU_DMAC_DMAREQ_MASK(upper);
144 
145 	guard(raw_spinlock_irqsave)(&priv->lock);
146 
147 	icu_dmksely = readl(priv->base + ICU_DMkSELy(dmac_index, y));
148 	icu_dmksely = (icu_dmksely & ~dmareq_mask) | dmareq;
149 	writel(icu_dmksely, priv->base + ICU_DMkSELy(dmac_index, y));
150 }
151 EXPORT_SYMBOL_GPL(rzv2h_icu_register_dma_req);
152 
irq_data_to_priv(struct irq_data * data)153 static inline struct rzv2h_icu_priv *irq_data_to_priv(struct irq_data *data)
154 {
155 	return data->domain->host_data;
156 }
157 
rzv2h_icu_eoi(struct irq_data * d)158 static void rzv2h_icu_eoi(struct irq_data *d)
159 {
160 	struct rzv2h_icu_priv *priv = irq_data_to_priv(d);
161 	unsigned int hw_irq = irqd_to_hwirq(d);
162 	unsigned int tintirq_nr;
163 	u32 bit;
164 
165 	scoped_guard(raw_spinlock, &priv->lock) {
166 		if (hw_irq >= ICU_TINT_START) {
167 			tintirq_nr = hw_irq - ICU_TINT_START;
168 			bit = BIT(tintirq_nr);
169 			if (!irqd_is_level_type(d))
170 				writel_relaxed(bit, priv->base + priv->info->t_offs + ICU_TSCLR);
171 		} else if (hw_irq >= ICU_IRQ_START) {
172 			tintirq_nr = hw_irq - ICU_IRQ_START;
173 			bit = BIT(tintirq_nr);
174 			if (!irqd_is_level_type(d))
175 				writel_relaxed(bit, priv->base + ICU_ISCLR);
176 		} else {
177 			writel_relaxed(ICU_NSCLR_NCLR, priv->base + ICU_NSCLR);
178 		}
179 	}
180 
181 	irq_chip_eoi_parent(d);
182 }
183 
rzv2h_tint_irq_endisable(struct irq_data * d,bool enable)184 static void rzv2h_tint_irq_endisable(struct irq_data *d, bool enable)
185 {
186 	struct rzv2h_icu_priv *priv = irq_data_to_priv(d);
187 	unsigned int hw_irq = irqd_to_hwirq(d);
188 	u32 tint_nr, tssel_n, k, tssr;
189 	u8 nr_tint;
190 
191 	if (hw_irq < ICU_TINT_START)
192 		return;
193 
194 	tint_nr = hw_irq - ICU_TINT_START;
195 	nr_tint = 32 / priv->info->field_width;
196 	k = tint_nr / nr_tint;
197 	tssel_n = tint_nr % nr_tint;
198 
199 	guard(raw_spinlock)(&priv->lock);
200 	tssr = readl_relaxed(priv->base + priv->info->t_offs + ICU_TSSR(k));
201 	if (enable)
202 		tssr |= ICU_TSSR_TIEN(tssel_n, priv->info->field_width);
203 	else
204 		tssr &= ~ICU_TSSR_TIEN(tssel_n, priv->info->field_width);
205 	writel_relaxed(tssr, priv->base + priv->info->t_offs + ICU_TSSR(k));
206 
207 	/*
208 	 * A glitch in the edge detection circuit can cause a spurious
209 	 * interrupt. Clear the status flag after setting the ICU_TSSRk
210 	 * registers, which is recommended by the hardware manual as a
211 	 * countermeasure.
212 	 */
213 	writel_relaxed(BIT(tint_nr), priv->base + priv->info->t_offs + ICU_TSCLR);
214 }
215 
rzv2h_icu_irq_disable(struct irq_data * d)216 static void rzv2h_icu_irq_disable(struct irq_data *d)
217 {
218 	irq_chip_disable_parent(d);
219 	rzv2h_tint_irq_endisable(d, false);
220 }
221 
rzv2h_icu_irq_enable(struct irq_data * d)222 static void rzv2h_icu_irq_enable(struct irq_data *d)
223 {
224 	rzv2h_tint_irq_endisable(d, true);
225 	irq_chip_enable_parent(d);
226 }
227 
rzv2h_nmi_set_type(struct irq_data * d,unsigned int type)228 static int rzv2h_nmi_set_type(struct irq_data *d, unsigned int type)
229 {
230 	struct rzv2h_icu_priv *priv = irq_data_to_priv(d);
231 	u32 sense;
232 
233 	switch (type & IRQ_TYPE_SENSE_MASK) {
234 	case IRQ_TYPE_EDGE_FALLING:
235 		sense = ICU_NMI_EDGE_FALLING;
236 		break;
237 
238 	case IRQ_TYPE_EDGE_RISING:
239 		sense = ICU_NMI_EDGE_RISING;
240 		break;
241 
242 	default:
243 		return -EINVAL;
244 	}
245 
246 	writel_relaxed(sense, priv->base + ICU_NITSR);
247 
248 	return 0;
249 }
250 
rzv2h_clear_irq_int(struct rzv2h_icu_priv * priv,unsigned int hwirq)251 static void rzv2h_clear_irq_int(struct rzv2h_icu_priv *priv, unsigned int hwirq)
252 {
253 	unsigned int irq_nr = hwirq - ICU_IRQ_START;
254 	u32 isctr, iitsr, iitsel;
255 	u32 bit = BIT(irq_nr);
256 
257 	isctr = readl_relaxed(priv->base + ICU_ISCTR);
258 	iitsr = readl_relaxed(priv->base + ICU_IITSR);
259 	iitsel = ICU_IITSR_IITSEL_GET(iitsr, irq_nr);
260 
261 	/*
262 	 * When level sensing is used, the interrupt flag gets automatically cleared when the
263 	 * interrupt signal is de-asserted by the source of the interrupt request, therefore clear
264 	 * the interrupt only for edge triggered interrupts.
265 	 */
266 	if ((isctr & bit) && (iitsel != ICU_IRQ_LEVEL_LOW))
267 		writel_relaxed(bit, priv->base + ICU_ISCLR);
268 }
269 
rzv2h_irq_set_type(struct irq_data * d,unsigned int type)270 static int rzv2h_irq_set_type(struct irq_data *d, unsigned int type)
271 {
272 	struct rzv2h_icu_priv *priv = irq_data_to_priv(d);
273 	unsigned int hwirq = irqd_to_hwirq(d);
274 	u32 irq_nr = hwirq - ICU_IRQ_START;
275 	u32 iitsr, sense;
276 
277 	switch (type & IRQ_TYPE_SENSE_MASK) {
278 	case IRQ_TYPE_LEVEL_LOW:
279 		sense = ICU_IRQ_LEVEL_LOW;
280 		break;
281 
282 	case IRQ_TYPE_EDGE_FALLING:
283 		sense = ICU_IRQ_EDGE_FALLING;
284 		break;
285 
286 	case IRQ_TYPE_EDGE_RISING:
287 		sense = ICU_IRQ_EDGE_RISING;
288 		break;
289 
290 	case IRQ_TYPE_EDGE_BOTH:
291 		sense = ICU_IRQ_EDGE_BOTH;
292 		break;
293 
294 	default:
295 		return -EINVAL;
296 	}
297 
298 	guard(raw_spinlock)(&priv->lock);
299 	iitsr = readl_relaxed(priv->base + ICU_IITSR);
300 	iitsr &= ~ICU_IITSR_IITSEL_MASK(irq_nr);
301 	iitsr |= ICU_IITSR_IITSEL_PREP(sense, irq_nr);
302 	rzv2h_clear_irq_int(priv, hwirq);
303 	writel_relaxed(iitsr, priv->base + ICU_IITSR);
304 
305 	return 0;
306 }
307 
rzv2h_clear_tint_int(struct rzv2h_icu_priv * priv,unsigned int hwirq)308 static void rzv2h_clear_tint_int(struct rzv2h_icu_priv *priv, unsigned int hwirq)
309 {
310 	unsigned int tint_nr = hwirq - ICU_TINT_START;
311 	int titsel_n = ICU_TITSR_TITSEL_N(tint_nr);
312 	u32 tsctr, titsr, titsel;
313 	u32 bit = BIT(tint_nr);
314 	int k = tint_nr / 16;
315 
316 	tsctr = readl_relaxed(priv->base + priv->info->t_offs + ICU_TSCTR);
317 	titsr = readl_relaxed(priv->base + priv->info->t_offs + ICU_TITSR(k));
318 	titsel = ICU_TITSR_TITSEL_GET(titsr, titsel_n);
319 
320 	/*
321 	 * Writing 1 to the corresponding flag from register ICU_TSCTR only has effect if
322 	 * TSTATn = 1b and if it's a rising edge or a falling edge interrupt.
323 	 */
324 	if ((tsctr & bit) && ((titsel == ICU_TINT_EDGE_RISING) ||
325 			      (titsel == ICU_TINT_EDGE_FALLING)))
326 		writel_relaxed(bit, priv->base + priv->info->t_offs + ICU_TSCLR);
327 }
328 
rzv2h_tint_set_type(struct irq_data * d,unsigned int type)329 static int rzv2h_tint_set_type(struct irq_data *d, unsigned int type)
330 {
331 	u32 titsr, titsr_k, titsel_n, tien;
332 	struct rzv2h_icu_priv *priv;
333 	u32 tssr, tssr_k, tssel_n;
334 	unsigned int hwirq;
335 	u32 tint, sense;
336 	int tint_nr;
337 	u8 nr_tint;
338 
339 	switch (type & IRQ_TYPE_SENSE_MASK) {
340 	case IRQ_TYPE_LEVEL_LOW:
341 		sense = ICU_TINT_LEVEL_LOW;
342 		break;
343 
344 	case IRQ_TYPE_LEVEL_HIGH:
345 		sense = ICU_TINT_LEVEL_HIGH;
346 		break;
347 
348 	case IRQ_TYPE_EDGE_RISING:
349 		sense = ICU_TINT_EDGE_RISING;
350 		break;
351 
352 	case IRQ_TYPE_EDGE_FALLING:
353 		sense = ICU_TINT_EDGE_FALLING;
354 		break;
355 
356 	default:
357 		return -EINVAL;
358 	}
359 
360 	priv = irq_data_to_priv(d);
361 	tint = (u32)(uintptr_t)irq_data_get_irq_chip_data(d);
362 	if (tint > priv->info->max_tssel)
363 		return -EINVAL;
364 
365 	if (priv->info->tssel_lut)
366 		tint = priv->info->tssel_lut[tint];
367 
368 	hwirq = irqd_to_hwirq(d);
369 	tint_nr = hwirq - ICU_TINT_START;
370 
371 	nr_tint = 32 / priv->info->field_width;
372 	tssr_k = tint_nr / nr_tint;
373 	tssel_n = tint_nr % nr_tint;
374 	tien = ICU_TSSR_TIEN(tssel_n, priv->info->field_width);
375 
376 	titsr_k = ICU_TITSR_K(tint_nr);
377 	titsel_n = ICU_TITSR_TITSEL_N(tint_nr);
378 
379 	guard(raw_spinlock)(&priv->lock);
380 
381 	tssr = readl_relaxed(priv->base + priv->info->t_offs + ICU_TSSR(tssr_k));
382 	tssr &= ~(ICU_TSSR_TSSEL_MASK(tssel_n, priv->info->field_width) | tien);
383 	tssr |= ICU_TSSR_TSSEL_PREP(tint, tssel_n, priv->info->field_width);
384 
385 	writel_relaxed(tssr, priv->base + priv->info->t_offs + ICU_TSSR(tssr_k));
386 
387 	titsr = readl_relaxed(priv->base + priv->info->t_offs + ICU_TITSR(titsr_k));
388 	titsr &= ~ICU_TITSR_TITSEL_MASK(titsel_n);
389 	titsr |= ICU_TITSR_TITSEL_PREP(sense, titsel_n);
390 
391 	writel_relaxed(titsr, priv->base + priv->info->t_offs + ICU_TITSR(titsr_k));
392 
393 	rzv2h_clear_tint_int(priv, hwirq);
394 
395 	writel_relaxed(tssr | tien, priv->base + priv->info->t_offs + ICU_TSSR(tssr_k));
396 
397 	return 0;
398 }
399 
rzv2h_icu_set_type(struct irq_data * d,unsigned int type)400 static int rzv2h_icu_set_type(struct irq_data *d, unsigned int type)
401 {
402 	unsigned int hw_irq = irqd_to_hwirq(d);
403 	int ret;
404 
405 	if (hw_irq >= ICU_TINT_START)
406 		ret = rzv2h_tint_set_type(d, type);
407 	else if (hw_irq >= ICU_IRQ_START)
408 		ret = rzv2h_irq_set_type(d, type);
409 	else
410 		ret = rzv2h_nmi_set_type(d, type);
411 
412 	if (ret)
413 		return ret;
414 
415 	return irq_chip_set_type_parent(d, IRQ_TYPE_LEVEL_HIGH);
416 }
417 
418 static const struct irq_chip rzv2h_icu_chip = {
419 	.name			= "rzv2h-icu",
420 	.irq_eoi		= rzv2h_icu_eoi,
421 	.irq_mask		= irq_chip_mask_parent,
422 	.irq_unmask		= irq_chip_unmask_parent,
423 	.irq_disable		= rzv2h_icu_irq_disable,
424 	.irq_enable		= rzv2h_icu_irq_enable,
425 	.irq_get_irqchip_state	= irq_chip_get_parent_state,
426 	.irq_set_irqchip_state	= irq_chip_set_parent_state,
427 	.irq_retrigger		= irq_chip_retrigger_hierarchy,
428 	.irq_set_type		= rzv2h_icu_set_type,
429 	.irq_set_affinity	= irq_chip_set_affinity_parent,
430 	.flags			= IRQCHIP_SET_TYPE_MASKED,
431 };
432 
rzv2h_icu_alloc(struct irq_domain * domain,unsigned int virq,unsigned int nr_irqs,void * arg)433 static int rzv2h_icu_alloc(struct irq_domain *domain, unsigned int virq, unsigned int nr_irqs,
434 			   void *arg)
435 {
436 	struct rzv2h_icu_priv *priv = domain->host_data;
437 	unsigned long tint = 0;
438 	irq_hw_number_t hwirq;
439 	unsigned int type;
440 	int ret;
441 
442 	ret = irq_domain_translate_twocell(domain, arg, &hwirq, &type);
443 	if (ret)
444 		return ret;
445 
446 	/*
447 	 * For TINT interrupts the hwirq and TINT are encoded in
448 	 * fwspec->param[0].
449 	 * hwirq is embedded in bits 0-15.
450 	 * TINT is embedded in bits 16-31.
451 	 */
452 	if (hwirq >= ICU_TINT_START) {
453 		tint = ICU_TINT_EXTRACT_GPIOINT(hwirq);
454 		hwirq = ICU_TINT_EXTRACT_HWIRQ(hwirq);
455 
456 		if (hwirq < ICU_TINT_START)
457 			return -EINVAL;
458 	}
459 
460 	if (hwirq > (ICU_NUM_IRQ - 1))
461 		return -EINVAL;
462 
463 	ret = irq_domain_set_hwirq_and_chip(domain, virq, hwirq, &rzv2h_icu_chip,
464 					    (void *)(uintptr_t)tint);
465 	if (ret)
466 		return ret;
467 
468 	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &priv->fwspec[hwirq]);
469 }
470 
471 static const struct irq_domain_ops rzv2h_icu_domain_ops = {
472 	.alloc		= rzv2h_icu_alloc,
473 	.free		= irq_domain_free_irqs_common,
474 	.translate	= irq_domain_translate_twocell,
475 };
476 
rzv2h_icu_parse_interrupts(struct rzv2h_icu_priv * priv,struct device_node * np)477 static int rzv2h_icu_parse_interrupts(struct rzv2h_icu_priv *priv, struct device_node *np)
478 {
479 	struct of_phandle_args map;
480 	unsigned int i;
481 	int ret;
482 
483 	for (i = 0; i < ICU_NUM_IRQ; i++) {
484 		ret = of_irq_parse_one(np, i, &map);
485 		if (ret)
486 			return ret;
487 
488 		of_phandle_args_to_fwspec(np, map.args, map.args_count, &priv->fwspec[i]);
489 	}
490 
491 	return 0;
492 }
493 
rzv2h_icu_put_device(void * data)494 static void rzv2h_icu_put_device(void *data)
495 {
496 	put_device(data);
497 }
498 
rzv2h_icu_init_common(struct device_node * node,struct device_node * parent,const struct rzv2h_hw_info * hw_info)499 static int rzv2h_icu_init_common(struct device_node *node, struct device_node *parent,
500 				 const struct rzv2h_hw_info *hw_info)
501 {
502 	struct irq_domain *irq_domain, *parent_domain;
503 	struct rzv2h_icu_priv *rzv2h_icu_data;
504 	struct platform_device *pdev;
505 	struct reset_control *resetn;
506 	int ret;
507 
508 	pdev = of_find_device_by_node(node);
509 	if (!pdev)
510 		return -ENODEV;
511 
512 	ret = devm_add_action_or_reset(&pdev->dev, rzv2h_icu_put_device,
513 				       &pdev->dev);
514 	if (ret < 0)
515 		return ret;
516 
517 	parent_domain = irq_find_host(parent);
518 	if (!parent_domain) {
519 		dev_err(&pdev->dev, "cannot find parent domain\n");
520 		return -ENODEV;
521 	}
522 
523 	rzv2h_icu_data = devm_kzalloc(&pdev->dev, sizeof(*rzv2h_icu_data), GFP_KERNEL);
524 	if (!rzv2h_icu_data)
525 		return -ENOMEM;
526 
527 	platform_set_drvdata(pdev, rzv2h_icu_data);
528 
529 	rzv2h_icu_data->base = devm_of_iomap(&pdev->dev, pdev->dev.of_node, 0, NULL);
530 	if (IS_ERR(rzv2h_icu_data->base))
531 		return PTR_ERR(rzv2h_icu_data->base);
532 
533 	ret = rzv2h_icu_parse_interrupts(rzv2h_icu_data, node);
534 	if (ret) {
535 		dev_err(&pdev->dev, "cannot parse interrupts: %d\n", ret);
536 		return ret;
537 	}
538 
539 	resetn = devm_reset_control_get_exclusive_deasserted(&pdev->dev, NULL);
540 	if (IS_ERR(resetn)) {
541 		ret = PTR_ERR(resetn);
542 		dev_err(&pdev->dev, "failed to acquire deasserted reset: %d\n", ret);
543 		return ret;
544 	}
545 
546 	ret = devm_pm_runtime_enable(&pdev->dev);
547 	if (ret < 0) {
548 		dev_err(&pdev->dev, "devm_pm_runtime_enable failed, %d\n", ret);
549 		return ret;
550 	}
551 
552 	ret = pm_runtime_resume_and_get(&pdev->dev);
553 	if (ret < 0) {
554 		dev_err(&pdev->dev, "pm_runtime_resume_and_get failed: %d\n", ret);
555 		return ret;
556 	}
557 
558 	raw_spin_lock_init(&rzv2h_icu_data->lock);
559 
560 	irq_domain = irq_domain_create_hierarchy(parent_domain, 0, ICU_NUM_IRQ,
561 						 of_fwnode_handle(node), &rzv2h_icu_domain_ops,
562 						 rzv2h_icu_data);
563 	if (!irq_domain) {
564 		dev_err(&pdev->dev, "failed to add irq domain\n");
565 		ret = -ENOMEM;
566 		goto pm_put;
567 	}
568 
569 	rzv2h_icu_data->info = hw_info;
570 
571 	/*
572 	 * coccicheck complains about a missing put_device call before returning, but it's a false
573 	 * positive. We still need &pdev->dev after successfully returning from this function.
574 	 */
575 	return 0;
576 
577 pm_put:
578 	pm_runtime_put(&pdev->dev);
579 
580 	return ret;
581 }
582 
583 /* Mapping based on port index on Table 4.2-6 and TSSEL bits on Table 4.6-4 */
584 static const u8 rzg3e_tssel_lut[] = {
585 	81, 82, 83, 84, 85, 86, 87, 88,		/* P00-P07 */
586 	89, 90, 91, 92, 93, 94, 95, 96,		/* P10-P17 */
587 	111, 112,				/* P20-P21 */
588 	97, 98, 99, 100, 101, 102, 103, 104,	/* P30-P37 */
589 	105, 106, 107, 108, 109, 110,		/* P40-P45 */
590 	113, 114, 115, 116, 117, 118, 119,	/* P50-P56 */
591 	120, 121, 122, 123, 124, 125, 126,	/* P60-P66 */
592 	127, 128, 129, 130, 131, 132, 133, 134,	/* P70-P77 */
593 	135, 136, 137, 138, 139, 140,		/* P80-P85 */
594 	43, 44, 45, 46, 47, 48, 49, 50,		/* PA0-PA7 */
595 	51, 52, 53, 54, 55, 56, 57, 58,		/* PB0-PB7 */
596 	59, 60,	61,				/* PC0-PC2 */
597 	62, 63, 64, 65, 66, 67, 68, 69,		/* PD0-PD7 */
598 	70, 71, 72, 73, 74, 75, 76, 77,		/* PE0-PE7 */
599 	78, 79, 80,				/* PF0-PF2 */
600 	25, 26, 27, 28, 29, 30, 31, 32,		/* PG0-PG7 */
601 	33, 34, 35, 36, 37, 38,			/* PH0-PH5 */
602 	4, 5, 6, 7, 8,				/* PJ0-PJ4 */
603 	39, 40, 41, 42,				/* PK0-PK3 */
604 	9, 10, 11, 12, 21, 22, 23, 24,		/* PL0-PL7 */
605 	13, 14, 15, 16, 17, 18, 19, 20,		/* PM0-PM7 */
606 	0, 1, 2, 3				/* PS0-PS3 */
607 };
608 
609 static const struct rzv2h_hw_info rzg3e_hw_params = {
610 	.tssel_lut	= rzg3e_tssel_lut,
611 	.t_offs		= ICU_RZG3E_TINT_OFFSET,
612 	.max_tssel	= ICU_RZG3E_TSSEL_MAX_VAL,
613 	.field_width	= 16,
614 };
615 
616 static const struct rzv2h_hw_info rzv2h_hw_params = {
617 	.t_offs		= 0,
618 	.max_tssel	= ICU_RZV2H_TSSEL_MAX_VAL,
619 	.field_width	= 8,
620 };
621 
rzg3e_icu_init(struct device_node * node,struct device_node * parent)622 static int rzg3e_icu_init(struct device_node *node, struct device_node *parent)
623 {
624 	return rzv2h_icu_init_common(node, parent, &rzg3e_hw_params);
625 }
626 
rzv2h_icu_init(struct device_node * node,struct device_node * parent)627 static int rzv2h_icu_init(struct device_node *node, struct device_node *parent)
628 {
629 	return rzv2h_icu_init_common(node, parent, &rzv2h_hw_params);
630 }
631 
632 IRQCHIP_PLATFORM_DRIVER_BEGIN(rzv2h_icu)
633 IRQCHIP_MATCH("renesas,r9a09g047-icu", rzg3e_icu_init)
634 IRQCHIP_MATCH("renesas,r9a09g057-icu", rzv2h_icu_init)
635 IRQCHIP_PLATFORM_DRIVER_END(rzv2h_icu)
636 MODULE_AUTHOR("Fabrizio Castro <fabrizio.castro.jz@renesas.com>");
637 MODULE_DESCRIPTION("Renesas RZ/V2H(P) ICU Driver");
638