diff options
Diffstat (limited to 'drivers/gpio/gpio-thunderx.c')
-rw-r--r-- | drivers/gpio/gpio-thunderx.c | 36 |
1 files changed, 32 insertions, 4 deletions
diff --git a/drivers/gpio/gpio-thunderx.c b/drivers/gpio/gpio-thunderx.c index d08d86a22b1f..9f66deab46ea 100644 --- a/drivers/gpio/gpio-thunderx.c +++ b/drivers/gpio/gpio-thunderx.c @@ -15,6 +15,7 @@ #include <linux/module.h> #include <linux/pci.h> #include <linux/spinlock.h> +#include <asm-generic/msi.h> #define GPIO_RX_DAT 0x0 @@ -395,12 +396,32 @@ static int thunderx_gpio_child_to_parent_hwirq(struct gpio_chip *gc, unsigned int *parent_type) { struct thunderx_gpio *txgpio = gpiochip_get_data(gc); - - *parent = txgpio->base_msi + (2 * child); + struct irq_data *irqd; + unsigned int irq; + + irq = txgpio->msix_entries[child].vector; + irqd = irq_domain_get_irq_data(gc->irq.parent_domain, irq); + if (!irqd) + return -EINVAL; + *parent = irqd_to_hwirq(irqd); *parent_type = IRQ_TYPE_LEVEL_HIGH; return 0; } +static void *thunderx_gpio_populate_parent_alloc_info(struct gpio_chip *chip, + unsigned int parent_hwirq, + unsigned int parent_type) +{ + msi_alloc_info_t *info; + + info = kmalloc(sizeof(*info), GFP_KERNEL); + if (!info) + return NULL; + + info->hwirq = parent_hwirq; + return info; +} + static int thunderx_gpio_probe(struct pci_dev *pdev, const struct pci_device_id *id) { @@ -515,6 +536,7 @@ static int thunderx_gpio_probe(struct pci_dev *pdev, girq->parent_domain = irq_get_irq_data(txgpio->msix_entries[0].vector)->domain; girq->child_to_parent_hwirq = thunderx_gpio_child_to_parent_hwirq; + girq->populate_parent_alloc_arg = thunderx_gpio_populate_parent_alloc_info; girq->handler = handle_bad_irq; girq->default_type = IRQ_TYPE_NONE; @@ -524,9 +546,15 @@ static int thunderx_gpio_probe(struct pci_dev *pdev, /* Push on irq_data and the domain for each line. */ for (i = 0; i < ngpio; i++) { - err = irq_domain_push_irq(chip->irq.domain, + struct irq_fwspec fwspec; + + fwspec.fwnode = of_node_to_fwnode(dev->of_node); + fwspec.param_count = 2; + fwspec.param[0] = i; + fwspec.param[1] = IRQ_TYPE_NONE; + err = irq_domain_push_irq(girq->domain, txgpio->msix_entries[i].vector, - chip); + &fwspec); if (err < 0) dev_err(dev, "irq_domain_push_irq: %d\n", err); } |