.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (c) 2011, Code Aurora Forum. All rights reserved. |
---|
3 | | - * |
---|
4 | | - * This program is free software; you can redistribute it and/or modify |
---|
5 | | - * it under the terms of the GNU General Public License version 2 and |
---|
6 | | - * only version 2 as published by the Free Software Foundation. |
---|
7 | | - * |
---|
8 | | - * This program is distributed in the hope that it will be useful, |
---|
9 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
10 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
11 | | - * GNU General Public License for more details. |
---|
12 | 4 | */ |
---|
13 | 5 | |
---|
14 | 6 | #define pr_fmt(fmt) "%s: " fmt, __func__ |
---|
.. | .. |
---|
70 | 62 | #define PM8XXX_NR_IRQS 256 |
---|
71 | 63 | #define PM8821_NR_IRQS 112 |
---|
72 | 64 | |
---|
| 65 | +struct pm_irq_data { |
---|
| 66 | + int num_irqs; |
---|
| 67 | + struct irq_chip *irq_chip; |
---|
| 68 | + void (*irq_handler)(struct irq_desc *desc); |
---|
| 69 | +}; |
---|
| 70 | + |
---|
73 | 71 | struct pm_irq_chip { |
---|
74 | 72 | struct regmap *regmap; |
---|
75 | 73 | spinlock_t pm_irq_lock; |
---|
76 | 74 | struct irq_domain *irqdomain; |
---|
77 | | - unsigned int num_irqs; |
---|
78 | 75 | unsigned int num_blocks; |
---|
79 | 76 | unsigned int num_masters; |
---|
80 | | - u8 config[0]; |
---|
81 | | -}; |
---|
82 | | - |
---|
83 | | -struct pm_irq_data { |
---|
84 | | - int num_irqs; |
---|
85 | | - const struct irq_domain_ops *irq_domain_ops; |
---|
86 | | - void (*irq_handler)(struct irq_desc *desc); |
---|
| 77 | + const struct pm_irq_data *pm_irq_data; |
---|
| 78 | + /* MUST BE AT THE END OF THIS STRUCT */ |
---|
| 79 | + u8 config[]; |
---|
87 | 80 | }; |
---|
88 | 81 | |
---|
89 | 82 | static int pm8xxx_read_block_irq(struct pm_irq_chip *chip, unsigned int bp, |
---|
.. | .. |
---|
375 | 368 | .flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE, |
---|
376 | 369 | }; |
---|
377 | 370 | |
---|
378 | | -static int pm8xxx_irq_domain_map(struct irq_domain *d, unsigned int irq, |
---|
379 | | - irq_hw_number_t hwirq) |
---|
| 371 | +static void pm8xxx_irq_domain_map(struct pm_irq_chip *chip, |
---|
| 372 | + struct irq_domain *domain, unsigned int irq, |
---|
| 373 | + irq_hw_number_t hwirq, unsigned int type) |
---|
380 | 374 | { |
---|
381 | | - struct pm_irq_chip *chip = d->host_data; |
---|
382 | | - |
---|
383 | | - irq_set_chip_and_handler(irq, &pm8xxx_irq_chip, handle_level_irq); |
---|
384 | | - irq_set_chip_data(irq, chip); |
---|
| 375 | + irq_domain_set_info(domain, irq, hwirq, chip->pm_irq_data->irq_chip, |
---|
| 376 | + chip, handle_level_irq, NULL, NULL); |
---|
385 | 377 | irq_set_noprobe(irq); |
---|
| 378 | +} |
---|
| 379 | + |
---|
| 380 | +static int pm8xxx_irq_domain_alloc(struct irq_domain *domain, unsigned int virq, |
---|
| 381 | + unsigned int nr_irqs, void *data) |
---|
| 382 | +{ |
---|
| 383 | + struct pm_irq_chip *chip = domain->host_data; |
---|
| 384 | + struct irq_fwspec *fwspec = data; |
---|
| 385 | + irq_hw_number_t hwirq; |
---|
| 386 | + unsigned int type; |
---|
| 387 | + int ret, i; |
---|
| 388 | + |
---|
| 389 | + ret = irq_domain_translate_twocell(domain, fwspec, &hwirq, &type); |
---|
| 390 | + if (ret) |
---|
| 391 | + return ret; |
---|
| 392 | + |
---|
| 393 | + for (i = 0; i < nr_irqs; i++) |
---|
| 394 | + pm8xxx_irq_domain_map(chip, domain, virq + i, hwirq + i, type); |
---|
386 | 395 | |
---|
387 | 396 | return 0; |
---|
388 | 397 | } |
---|
389 | 398 | |
---|
390 | 399 | static const struct irq_domain_ops pm8xxx_irq_domain_ops = { |
---|
391 | | - .xlate = irq_domain_xlate_twocell, |
---|
392 | | - .map = pm8xxx_irq_domain_map, |
---|
| 400 | + .alloc = pm8xxx_irq_domain_alloc, |
---|
| 401 | + .free = irq_domain_free_irqs_common, |
---|
| 402 | + .translate = irq_domain_translate_twocell, |
---|
393 | 403 | }; |
---|
394 | 404 | |
---|
395 | 405 | static void pm8821_irq_mask_ack(struct irq_data *d) |
---|
.. | .. |
---|
473 | 483 | .flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE, |
---|
474 | 484 | }; |
---|
475 | 485 | |
---|
476 | | -static int pm8821_irq_domain_map(struct irq_domain *d, unsigned int irq, |
---|
477 | | - irq_hw_number_t hwirq) |
---|
478 | | -{ |
---|
479 | | - struct pm_irq_chip *chip = d->host_data; |
---|
480 | | - |
---|
481 | | - irq_set_chip_and_handler(irq, &pm8821_irq_chip, handle_level_irq); |
---|
482 | | - irq_set_chip_data(irq, chip); |
---|
483 | | - irq_set_noprobe(irq); |
---|
484 | | - |
---|
485 | | - return 0; |
---|
486 | | -} |
---|
487 | | - |
---|
488 | | -static const struct irq_domain_ops pm8821_irq_domain_ops = { |
---|
489 | | - .xlate = irq_domain_xlate_twocell, |
---|
490 | | - .map = pm8821_irq_domain_map, |
---|
491 | | -}; |
---|
492 | | - |
---|
493 | 486 | static const struct regmap_config ssbi_regmap_config = { |
---|
494 | 487 | .reg_bits = 16, |
---|
495 | 488 | .val_bits = 8, |
---|
.. | .. |
---|
501 | 494 | |
---|
502 | 495 | static const struct pm_irq_data pm8xxx_data = { |
---|
503 | 496 | .num_irqs = PM8XXX_NR_IRQS, |
---|
504 | | - .irq_domain_ops = &pm8xxx_irq_domain_ops, |
---|
| 497 | + .irq_chip = &pm8xxx_irq_chip, |
---|
505 | 498 | .irq_handler = pm8xxx_irq_handler, |
---|
506 | 499 | }; |
---|
507 | 500 | |
---|
508 | 501 | static const struct pm_irq_data pm8821_data = { |
---|
509 | 502 | .num_irqs = PM8821_NR_IRQS, |
---|
510 | | - .irq_domain_ops = &pm8821_irq_domain_ops, |
---|
| 503 | + .irq_chip = &pm8821_irq_chip, |
---|
511 | 504 | .irq_handler = pm8821_irq_handler, |
---|
512 | 505 | }; |
---|
513 | 506 | |
---|
.. | .. |
---|
571 | 564 | |
---|
572 | 565 | platform_set_drvdata(pdev, chip); |
---|
573 | 566 | chip->regmap = regmap; |
---|
574 | | - chip->num_irqs = data->num_irqs; |
---|
575 | | - chip->num_blocks = DIV_ROUND_UP(chip->num_irqs, 8); |
---|
| 567 | + chip->num_blocks = DIV_ROUND_UP(data->num_irqs, 8); |
---|
576 | 568 | chip->num_masters = DIV_ROUND_UP(chip->num_blocks, 8); |
---|
| 569 | + chip->pm_irq_data = data; |
---|
577 | 570 | spin_lock_init(&chip->pm_irq_lock); |
---|
578 | 571 | |
---|
579 | 572 | chip->irqdomain = irq_domain_add_linear(pdev->dev.of_node, |
---|
580 | 573 | data->num_irqs, |
---|
581 | | - data->irq_domain_ops, |
---|
| 574 | + &pm8xxx_irq_domain_ops, |
---|
582 | 575 | chip); |
---|
583 | 576 | if (!chip->irqdomain) |
---|
584 | 577 | return -ENODEV; |
---|