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