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