|
18 | 18 | #include <linux/of_irq.h> |
19 | 19 | #include <linux/of_platform.h> |
20 | 20 | #include <linux/irqchip/chained_irq.h> |
| 21 | +#include <linux/soc/ti/ti_sci_inta_msi.h> |
21 | 22 | #include <linux/soc/ti/ti_sci_protocol.h> |
22 | 23 | #include <asm-generic/msi.h> |
23 | 24 |
|
|
28 | 29 | #define HWIRQ_TO_DEVID(hwirq) (((hwirq) >> (TI_SCI_DEV_ID_SHIFT)) & \ |
29 | 30 | (TI_SCI_DEV_ID_MASK)) |
30 | 31 | #define HWIRQ_TO_IRQID(hwirq) ((hwirq) & (TI_SCI_IRQ_ID_MASK)) |
| 32 | +#define TO_HWIRQ(dev, index) ((((dev) & TI_SCI_DEV_ID_MASK) << \ |
| 33 | + TI_SCI_DEV_ID_SHIFT) | \ |
| 34 | + ((index) & TI_SCI_IRQ_ID_MASK)) |
31 | 35 |
|
32 | 36 | #define MAX_EVENTS_PER_VINT 64 |
33 | 37 | #define VINT_ENABLE_SET_OFFSET 0x0 |
@@ -484,9 +488,34 @@ static const struct irq_domain_ops ti_sci_inta_irq_domain_ops = { |
484 | 488 | .alloc = ti_sci_inta_irq_domain_alloc, |
485 | 489 | }; |
486 | 490 |
|
| 491 | +static struct irq_chip ti_sci_inta_msi_irq_chip = { |
| 492 | + .name = "MSI-INTA", |
| 493 | + .flags = IRQCHIP_SUPPORTS_LEVEL_MSI, |
| 494 | +}; |
| 495 | + |
| 496 | +static void ti_sci_inta_msi_set_desc(msi_alloc_info_t *arg, |
| 497 | + struct msi_desc *desc) |
| 498 | +{ |
| 499 | + struct platform_device *pdev = to_platform_device(desc->dev); |
| 500 | + |
| 501 | + arg->desc = desc; |
| 502 | + arg->hwirq = TO_HWIRQ(pdev->id, desc->inta.dev_index); |
| 503 | +} |
| 504 | + |
| 505 | +static struct msi_domain_ops ti_sci_inta_msi_ops = { |
| 506 | + .set_desc = ti_sci_inta_msi_set_desc, |
| 507 | +}; |
| 508 | + |
| 509 | +static struct msi_domain_info ti_sci_inta_msi_domain_info = { |
| 510 | + .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | |
| 511 | + MSI_FLAG_LEVEL_CAPABLE), |
| 512 | + .ops = &ti_sci_inta_msi_ops, |
| 513 | + .chip = &ti_sci_inta_msi_irq_chip, |
| 514 | +}; |
| 515 | + |
487 | 516 | static int ti_sci_inta_irq_domain_probe(struct platform_device *pdev) |
488 | 517 | { |
489 | | - struct irq_domain *parent_domain, *domain; |
| 518 | + struct irq_domain *parent_domain, *domain, *msi_domain; |
490 | 519 | struct device_node *parent_node, *node; |
491 | 520 | struct ti_sci_inta_irq_domain *inta; |
492 | 521 | struct device *dev = &pdev->dev; |
@@ -551,6 +580,15 @@ static int ti_sci_inta_irq_domain_probe(struct platform_device *pdev) |
551 | 580 | return -ENOMEM; |
552 | 581 | } |
553 | 582 |
|
| 583 | + msi_domain = ti_sci_inta_msi_create_irq_domain(of_node_to_fwnode(node), |
| 584 | + &ti_sci_inta_msi_domain_info, |
| 585 | + domain); |
| 586 | + if (!msi_domain) { |
| 587 | + irq_domain_remove(domain); |
| 588 | + dev_err(dev, "Failed to allocate msi domain\n"); |
| 589 | + return -ENOMEM; |
| 590 | + } |
| 591 | + |
554 | 592 | INIT_LIST_HEAD(&inta->vint_list); |
555 | 593 | mutex_init(&inta->vint_mutex); |
556 | 594 |
|
|
0 commit comments