Loading drivers/gpio/gpio-tegra186.c +10 −3 Original line number Diff line number Diff line Loading @@ -448,17 +448,24 @@ static int tegra186_gpio_irq_domain_translate(struct irq_domain *domain, return 0; } static void tegra186_gpio_populate_parent_fwspec(struct gpio_chip *chip, struct irq_fwspec *fwspec, static void *tegra186_gpio_populate_parent_fwspec(struct gpio_chip *chip, unsigned int parent_hwirq, unsigned int parent_type) { struct tegra_gpio *gpio = gpiochip_get_data(chip); struct irq_fwspec *fwspec; fwspec = kmalloc(sizeof(*fwspec), GFP_KERNEL); if (!fwspec) return NULL; fwspec->fwnode = chip->irq.parent_domain->fwnode; fwspec->param_count = 3; fwspec->param[0] = gpio->soc->instance; fwspec->param[1] = parent_hwirq; fwspec->param[2] = parent_type; return fwspec; } static int tegra186_gpio_child_to_parent_hwirq(struct gpio_chip *chip, Loading Loading @@ -621,7 +628,7 @@ static int tegra186_gpio_probe(struct platform_device *pdev) irq->chip = &gpio->intc; irq->fwnode = of_node_to_fwnode(pdev->dev.of_node); irq->child_to_parent_hwirq = tegra186_gpio_child_to_parent_hwirq; irq->populate_parent_fwspec = tegra186_gpio_populate_parent_fwspec; irq->populate_parent_alloc_arg = tegra186_gpio_populate_parent_fwspec; irq->child_offset_to_irq = tegra186_gpio_child_offset_to_irq; irq->child_irq_domain_ops.translate = tegra186_gpio_irq_domain_translate; irq->handler = handle_simple_irq; Loading drivers/gpio/gpio-thunderx.c +32 −4 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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) { Loading Loading @@ -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; Loading @@ -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); } Loading drivers/gpio/gpiolib.c +35 −16 Original line number Diff line number Diff line Loading @@ -1990,7 +1990,7 @@ static int gpiochip_hierarchy_irq_domain_alloc(struct irq_domain *d, irq_hw_number_t hwirq; unsigned int type = IRQ_TYPE_NONE; struct irq_fwspec *fwspec = data; struct irq_fwspec parent_fwspec; void *parent_arg; unsigned int parent_hwirq; unsigned int parent_type; struct gpio_irq_chip *girq = &gc->irq; Loading Loading @@ -2029,24 +2029,27 @@ static int gpiochip_hierarchy_irq_domain_alloc(struct irq_domain *d, NULL, NULL); irq_set_probe(irq); /* * Create a IRQ fwspec to send up to the parent irqdomain: * specify the hwirq we address on the parent and tie it * all together up the chain. */ parent_fwspec.fwnode = d->parent->fwnode; /* This parent only handles asserted level IRQs */ girq->populate_parent_fwspec(gc, &parent_fwspec, parent_hwirq, parent_type); parent_arg = girq->populate_parent_alloc_arg(gc, parent_hwirq, parent_type); if (!parent_arg) return -ENOMEM; chip_info(gc, "alloc_irqs_parent for %d parent hwirq %d\n", irq, parent_hwirq); irq_set_lockdep_class(irq, gc->irq.lock_key, gc->irq.request_key); ret = irq_domain_alloc_irqs_parent(d, irq, 1, &parent_fwspec); ret = irq_domain_alloc_irqs_parent(d, irq, 1, parent_arg); /* * If the parent irqdomain is msi, the interrupts have already * been allocated, so the EEXIST is good. */ if (irq_domain_is_msi(d->parent) && (ret == -EEXIST)) ret = 0; if (ret) chip_err(gc, "failed to allocate parent hwirq %d for hwirq %lu\n", parent_hwirq, hwirq); kfree(parent_arg); return ret; } Loading Loading @@ -2083,8 +2086,8 @@ static int gpiochip_hierarchy_add_domain(struct gpio_chip *gc) if (!gc->irq.child_offset_to_irq) gc->irq.child_offset_to_irq = gpiochip_child_offset_to_irq_noop; if (!gc->irq.populate_parent_fwspec) gc->irq.populate_parent_fwspec = if (!gc->irq.populate_parent_alloc_arg) gc->irq.populate_parent_alloc_arg = gpiochip_populate_parent_fwspec_twocell; gpiochip_hierarchy_setup_domain_ops(&gc->irq.child_irq_domain_ops); Loading @@ -2110,27 +2113,43 @@ static bool gpiochip_hierarchy_is_hierarchical(struct gpio_chip *gc) return !!gc->irq.parent_domain; } void gpiochip_populate_parent_fwspec_twocell(struct gpio_chip *chip, struct irq_fwspec *fwspec, void *gpiochip_populate_parent_fwspec_twocell(struct gpio_chip *chip, unsigned int parent_hwirq, unsigned int parent_type) { struct irq_fwspec *fwspec; fwspec = kmalloc(sizeof(*fwspec), GFP_KERNEL); if (!fwspec) return NULL; fwspec->fwnode = chip->irq.parent_domain->fwnode; fwspec->param_count = 2; fwspec->param[0] = parent_hwirq; fwspec->param[1] = parent_type; return fwspec; } EXPORT_SYMBOL_GPL(gpiochip_populate_parent_fwspec_twocell); void gpiochip_populate_parent_fwspec_fourcell(struct gpio_chip *chip, struct irq_fwspec *fwspec, void *gpiochip_populate_parent_fwspec_fourcell(struct gpio_chip *chip, unsigned int parent_hwirq, unsigned int parent_type) { struct irq_fwspec *fwspec; fwspec = kmalloc(sizeof(*fwspec), GFP_KERNEL); if (!fwspec) return NULL; fwspec->fwnode = chip->irq.parent_domain->fwnode; fwspec->param_count = 4; fwspec->param[0] = 0; fwspec->param[1] = parent_hwirq; fwspec->param[2] = 0; fwspec->param[3] = parent_type; return fwspec; } EXPORT_SYMBOL_GPL(gpiochip_populate_parent_fwspec_fourcell); Loading drivers/pinctrl/qcom/pinctrl-spmi-gpio.c +1 −1 Original line number Diff line number Diff line Loading @@ -1060,7 +1060,7 @@ static int pmic_gpio_probe(struct platform_device *pdev) girq->fwnode = of_node_to_fwnode(state->dev->of_node); girq->parent_domain = parent_domain; girq->child_to_parent_hwirq = pmic_gpio_child_to_parent_hwirq; girq->populate_parent_fwspec = gpiochip_populate_parent_fwspec_fourcell; girq->populate_parent_alloc_arg = gpiochip_populate_parent_fwspec_fourcell; girq->child_offset_to_irq = pmic_gpio_child_offset_to_irq; girq->child_irq_domain_ops.translate = pmic_gpio_domain_translate; Loading drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c +1 −1 Original line number Diff line number Diff line Loading @@ -794,7 +794,7 @@ static int pm8xxx_gpio_probe(struct platform_device *pdev) girq->fwnode = of_node_to_fwnode(pctrl->dev->of_node); girq->parent_domain = parent_domain; girq->child_to_parent_hwirq = pm8xxx_child_to_parent_hwirq; girq->populate_parent_fwspec = gpiochip_populate_parent_fwspec_fourcell; girq->populate_parent_alloc_arg = gpiochip_populate_parent_fwspec_fourcell; girq->child_offset_to_irq = pm8xxx_child_offset_to_irq; girq->child_irq_domain_ops.translate = pm8xxx_domain_translate; Loading Loading
drivers/gpio/gpio-tegra186.c +10 −3 Original line number Diff line number Diff line Loading @@ -448,17 +448,24 @@ static int tegra186_gpio_irq_domain_translate(struct irq_domain *domain, return 0; } static void tegra186_gpio_populate_parent_fwspec(struct gpio_chip *chip, struct irq_fwspec *fwspec, static void *tegra186_gpio_populate_parent_fwspec(struct gpio_chip *chip, unsigned int parent_hwirq, unsigned int parent_type) { struct tegra_gpio *gpio = gpiochip_get_data(chip); struct irq_fwspec *fwspec; fwspec = kmalloc(sizeof(*fwspec), GFP_KERNEL); if (!fwspec) return NULL; fwspec->fwnode = chip->irq.parent_domain->fwnode; fwspec->param_count = 3; fwspec->param[0] = gpio->soc->instance; fwspec->param[1] = parent_hwirq; fwspec->param[2] = parent_type; return fwspec; } static int tegra186_gpio_child_to_parent_hwirq(struct gpio_chip *chip, Loading Loading @@ -621,7 +628,7 @@ static int tegra186_gpio_probe(struct platform_device *pdev) irq->chip = &gpio->intc; irq->fwnode = of_node_to_fwnode(pdev->dev.of_node); irq->child_to_parent_hwirq = tegra186_gpio_child_to_parent_hwirq; irq->populate_parent_fwspec = tegra186_gpio_populate_parent_fwspec; irq->populate_parent_alloc_arg = tegra186_gpio_populate_parent_fwspec; irq->child_offset_to_irq = tegra186_gpio_child_offset_to_irq; irq->child_irq_domain_ops.translate = tegra186_gpio_irq_domain_translate; irq->handler = handle_simple_irq; Loading
drivers/gpio/gpio-thunderx.c +32 −4 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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) { Loading Loading @@ -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; Loading @@ -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); } Loading
drivers/gpio/gpiolib.c +35 −16 Original line number Diff line number Diff line Loading @@ -1990,7 +1990,7 @@ static int gpiochip_hierarchy_irq_domain_alloc(struct irq_domain *d, irq_hw_number_t hwirq; unsigned int type = IRQ_TYPE_NONE; struct irq_fwspec *fwspec = data; struct irq_fwspec parent_fwspec; void *parent_arg; unsigned int parent_hwirq; unsigned int parent_type; struct gpio_irq_chip *girq = &gc->irq; Loading Loading @@ -2029,24 +2029,27 @@ static int gpiochip_hierarchy_irq_domain_alloc(struct irq_domain *d, NULL, NULL); irq_set_probe(irq); /* * Create a IRQ fwspec to send up to the parent irqdomain: * specify the hwirq we address on the parent and tie it * all together up the chain. */ parent_fwspec.fwnode = d->parent->fwnode; /* This parent only handles asserted level IRQs */ girq->populate_parent_fwspec(gc, &parent_fwspec, parent_hwirq, parent_type); parent_arg = girq->populate_parent_alloc_arg(gc, parent_hwirq, parent_type); if (!parent_arg) return -ENOMEM; chip_info(gc, "alloc_irqs_parent for %d parent hwirq %d\n", irq, parent_hwirq); irq_set_lockdep_class(irq, gc->irq.lock_key, gc->irq.request_key); ret = irq_domain_alloc_irqs_parent(d, irq, 1, &parent_fwspec); ret = irq_domain_alloc_irqs_parent(d, irq, 1, parent_arg); /* * If the parent irqdomain is msi, the interrupts have already * been allocated, so the EEXIST is good. */ if (irq_domain_is_msi(d->parent) && (ret == -EEXIST)) ret = 0; if (ret) chip_err(gc, "failed to allocate parent hwirq %d for hwirq %lu\n", parent_hwirq, hwirq); kfree(parent_arg); return ret; } Loading Loading @@ -2083,8 +2086,8 @@ static int gpiochip_hierarchy_add_domain(struct gpio_chip *gc) if (!gc->irq.child_offset_to_irq) gc->irq.child_offset_to_irq = gpiochip_child_offset_to_irq_noop; if (!gc->irq.populate_parent_fwspec) gc->irq.populate_parent_fwspec = if (!gc->irq.populate_parent_alloc_arg) gc->irq.populate_parent_alloc_arg = gpiochip_populate_parent_fwspec_twocell; gpiochip_hierarchy_setup_domain_ops(&gc->irq.child_irq_domain_ops); Loading @@ -2110,27 +2113,43 @@ static bool gpiochip_hierarchy_is_hierarchical(struct gpio_chip *gc) return !!gc->irq.parent_domain; } void gpiochip_populate_parent_fwspec_twocell(struct gpio_chip *chip, struct irq_fwspec *fwspec, void *gpiochip_populate_parent_fwspec_twocell(struct gpio_chip *chip, unsigned int parent_hwirq, unsigned int parent_type) { struct irq_fwspec *fwspec; fwspec = kmalloc(sizeof(*fwspec), GFP_KERNEL); if (!fwspec) return NULL; fwspec->fwnode = chip->irq.parent_domain->fwnode; fwspec->param_count = 2; fwspec->param[0] = parent_hwirq; fwspec->param[1] = parent_type; return fwspec; } EXPORT_SYMBOL_GPL(gpiochip_populate_parent_fwspec_twocell); void gpiochip_populate_parent_fwspec_fourcell(struct gpio_chip *chip, struct irq_fwspec *fwspec, void *gpiochip_populate_parent_fwspec_fourcell(struct gpio_chip *chip, unsigned int parent_hwirq, unsigned int parent_type) { struct irq_fwspec *fwspec; fwspec = kmalloc(sizeof(*fwspec), GFP_KERNEL); if (!fwspec) return NULL; fwspec->fwnode = chip->irq.parent_domain->fwnode; fwspec->param_count = 4; fwspec->param[0] = 0; fwspec->param[1] = parent_hwirq; fwspec->param[2] = 0; fwspec->param[3] = parent_type; return fwspec; } EXPORT_SYMBOL_GPL(gpiochip_populate_parent_fwspec_fourcell); Loading
drivers/pinctrl/qcom/pinctrl-spmi-gpio.c +1 −1 Original line number Diff line number Diff line Loading @@ -1060,7 +1060,7 @@ static int pmic_gpio_probe(struct platform_device *pdev) girq->fwnode = of_node_to_fwnode(state->dev->of_node); girq->parent_domain = parent_domain; girq->child_to_parent_hwirq = pmic_gpio_child_to_parent_hwirq; girq->populate_parent_fwspec = gpiochip_populate_parent_fwspec_fourcell; girq->populate_parent_alloc_arg = gpiochip_populate_parent_fwspec_fourcell; girq->child_offset_to_irq = pmic_gpio_child_offset_to_irq; girq->child_irq_domain_ops.translate = pmic_gpio_domain_translate; Loading
drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c +1 −1 Original line number Diff line number Diff line Loading @@ -794,7 +794,7 @@ static int pm8xxx_gpio_probe(struct platform_device *pdev) girq->fwnode = of_node_to_fwnode(pctrl->dev->of_node); girq->parent_domain = parent_domain; girq->child_to_parent_hwirq = pm8xxx_child_to_parent_hwirq; girq->populate_parent_fwspec = gpiochip_populate_parent_fwspec_fourcell; girq->populate_parent_alloc_arg = gpiochip_populate_parent_fwspec_fourcell; girq->child_offset_to_irq = pm8xxx_child_offset_to_irq; girq->child_irq_domain_ops.translate = pm8xxx_domain_translate; Loading