Skip to content

Commit 2425876

Browse files
haokexinlinusw
authored andcommitted
gpiolib: Add support for the irqdomain which doesn't use irq_fwspec as arg
Some gpio's parent irqdomain may not use the struct irq_fwspec as argument, such as msi irqdomain. So rename the callback populate_parent_fwspec() to populate_parent_alloc_arg() and make it allocate and populate the specific struct which is needed by the parent irqdomain. Signed-off-by: Kevin Hao <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Linus Walleij <[email protected]>
1 parent a564ac3 commit 2425876

File tree

5 files changed

+49
-34
lines changed

5 files changed

+49
-34
lines changed

drivers/gpio/gpio-tegra186.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -448,17 +448,24 @@ static int tegra186_gpio_irq_domain_translate(struct irq_domain *domain,
448448
return 0;
449449
}
450450

451-
static void tegra186_gpio_populate_parent_fwspec(struct gpio_chip *chip,
452-
struct irq_fwspec *fwspec,
451+
static void *tegra186_gpio_populate_parent_fwspec(struct gpio_chip *chip,
453452
unsigned int parent_hwirq,
454453
unsigned int parent_type)
455454
{
456455
struct tegra_gpio *gpio = gpiochip_get_data(chip);
456+
struct irq_fwspec *fwspec;
457457

458+
fwspec = kmalloc(sizeof(*fwspec), GFP_KERNEL);
459+
if (!fwspec)
460+
return NULL;
461+
462+
fwspec->fwnode = chip->irq.parent_domain->fwnode;
458463
fwspec->param_count = 3;
459464
fwspec->param[0] = gpio->soc->instance;
460465
fwspec->param[1] = parent_hwirq;
461466
fwspec->param[2] = parent_type;
467+
468+
return fwspec;
462469
}
463470

464471
static int tegra186_gpio_child_to_parent_hwirq(struct gpio_chip *chip,
@@ -621,7 +628,7 @@ static int tegra186_gpio_probe(struct platform_device *pdev)
621628
irq->chip = &gpio->intc;
622629
irq->fwnode = of_node_to_fwnode(pdev->dev.of_node);
623630
irq->child_to_parent_hwirq = tegra186_gpio_child_to_parent_hwirq;
624-
irq->populate_parent_fwspec = tegra186_gpio_populate_parent_fwspec;
631+
irq->populate_parent_alloc_arg = tegra186_gpio_populate_parent_fwspec;
625632
irq->child_offset_to_irq = tegra186_gpio_child_offset_to_irq;
626633
irq->child_irq_domain_ops.translate = tegra186_gpio_irq_domain_translate;
627634
irq->handler = handle_simple_irq;

drivers/gpio/gpiolib.c

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2003,7 +2003,7 @@ static int gpiochip_hierarchy_irq_domain_alloc(struct irq_domain *d,
20032003
irq_hw_number_t hwirq;
20042004
unsigned int type = IRQ_TYPE_NONE;
20052005
struct irq_fwspec *fwspec = data;
2006-
struct irq_fwspec parent_fwspec;
2006+
void *parent_arg;
20072007
unsigned int parent_hwirq;
20082008
unsigned int parent_type;
20092009
struct gpio_irq_chip *girq = &gc->irq;
@@ -2042,23 +2042,20 @@ static int gpiochip_hierarchy_irq_domain_alloc(struct irq_domain *d,
20422042
NULL, NULL);
20432043
irq_set_probe(irq);
20442044

2045-
/*
2046-
* Create a IRQ fwspec to send up to the parent irqdomain:
2047-
* specify the hwirq we address on the parent and tie it
2048-
* all together up the chain.
2049-
*/
2050-
parent_fwspec.fwnode = d->parent->fwnode;
20512045
/* This parent only handles asserted level IRQs */
2052-
girq->populate_parent_fwspec(gc, &parent_fwspec, parent_hwirq,
2053-
parent_type);
2046+
parent_arg = girq->populate_parent_alloc_arg(gc, parent_hwirq, parent_type);
2047+
if (!parent_arg)
2048+
return -ENOMEM;
2049+
20542050
chip_info(gc, "alloc_irqs_parent for %d parent hwirq %d\n",
20552051
irq, parent_hwirq);
2056-
ret = irq_domain_alloc_irqs_parent(d, irq, 1, &parent_fwspec);
2052+
ret = irq_domain_alloc_irqs_parent(d, irq, 1, parent_arg);
20572053
if (ret)
20582054
chip_err(gc,
20592055
"failed to allocate parent hwirq %d for hwirq %lu\n",
20602056
parent_hwirq, hwirq);
20612057

2058+
kfree(parent_arg);
20622059
return ret;
20632060
}
20642061

@@ -2095,8 +2092,8 @@ static int gpiochip_hierarchy_add_domain(struct gpio_chip *gc)
20952092
if (!gc->irq.child_offset_to_irq)
20962093
gc->irq.child_offset_to_irq = gpiochip_child_offset_to_irq_noop;
20972094

2098-
if (!gc->irq.populate_parent_fwspec)
2099-
gc->irq.populate_parent_fwspec =
2095+
if (!gc->irq.populate_parent_alloc_arg)
2096+
gc->irq.populate_parent_alloc_arg =
21002097
gpiochip_populate_parent_fwspec_twocell;
21012098

21022099
gpiochip_hierarchy_setup_domain_ops(&gc->irq.child_irq_domain_ops);
@@ -2122,27 +2119,43 @@ static bool gpiochip_hierarchy_is_hierarchical(struct gpio_chip *gc)
21222119
return !!gc->irq.parent_domain;
21232120
}
21242121

2125-
void gpiochip_populate_parent_fwspec_twocell(struct gpio_chip *chip,
2126-
struct irq_fwspec *fwspec,
2122+
void *gpiochip_populate_parent_fwspec_twocell(struct gpio_chip *chip,
21272123
unsigned int parent_hwirq,
21282124
unsigned int parent_type)
21292125
{
2126+
struct irq_fwspec *fwspec;
2127+
2128+
fwspec = kmalloc(sizeof(*fwspec), GFP_KERNEL);
2129+
if (!fwspec)
2130+
return NULL;
2131+
2132+
fwspec->fwnode = chip->irq.parent_domain->fwnode;
21302133
fwspec->param_count = 2;
21312134
fwspec->param[0] = parent_hwirq;
21322135
fwspec->param[1] = parent_type;
2136+
2137+
return fwspec;
21332138
}
21342139
EXPORT_SYMBOL_GPL(gpiochip_populate_parent_fwspec_twocell);
21352140

2136-
void gpiochip_populate_parent_fwspec_fourcell(struct gpio_chip *chip,
2137-
struct irq_fwspec *fwspec,
2141+
void *gpiochip_populate_parent_fwspec_fourcell(struct gpio_chip *chip,
21382142
unsigned int parent_hwirq,
21392143
unsigned int parent_type)
21402144
{
2145+
struct irq_fwspec *fwspec;
2146+
2147+
fwspec = kmalloc(sizeof(*fwspec), GFP_KERNEL);
2148+
if (!fwspec)
2149+
return NULL;
2150+
2151+
fwspec->fwnode = chip->irq.parent_domain->fwnode;
21412152
fwspec->param_count = 4;
21422153
fwspec->param[0] = 0;
21432154
fwspec->param[1] = parent_hwirq;
21442155
fwspec->param[2] = 0;
21452156
fwspec->param[3] = parent_type;
2157+
2158+
return fwspec;
21462159
}
21472160
EXPORT_SYMBOL_GPL(gpiochip_populate_parent_fwspec_fourcell);
21482161

drivers/pinctrl/qcom/pinctrl-spmi-gpio.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1060,7 +1060,7 @@ static int pmic_gpio_probe(struct platform_device *pdev)
10601060
girq->fwnode = of_node_to_fwnode(state->dev->of_node);
10611061
girq->parent_domain = parent_domain;
10621062
girq->child_to_parent_hwirq = pmic_gpio_child_to_parent_hwirq;
1063-
girq->populate_parent_fwspec = gpiochip_populate_parent_fwspec_fourcell;
1063+
girq->populate_parent_alloc_arg = gpiochip_populate_parent_fwspec_fourcell;
10641064
girq->child_offset_to_irq = pmic_gpio_child_offset_to_irq;
10651065
girq->child_irq_domain_ops.translate = pmic_gpio_domain_translate;
10661066

drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -794,7 +794,7 @@ static int pm8xxx_gpio_probe(struct platform_device *pdev)
794794
girq->fwnode = of_node_to_fwnode(pctrl->dev->of_node);
795795
girq->parent_domain = parent_domain;
796796
girq->child_to_parent_hwirq = pm8xxx_child_to_parent_hwirq;
797-
girq->populate_parent_fwspec = gpiochip_populate_parent_fwspec_fourcell;
797+
girq->populate_parent_alloc_arg = gpiochip_populate_parent_fwspec_fourcell;
798798
girq->child_offset_to_irq = pm8xxx_child_offset_to_irq;
799799
girq->child_irq_domain_ops.translate = pm8xxx_domain_translate;
800800

include/linux/gpio/driver.h

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -94,16 +94,15 @@ struct gpio_irq_chip {
9494
unsigned int *parent_type);
9595

9696
/**
97-
* @populate_parent_fwspec:
97+
* @populate_parent_alloc_arg :
9898
*
99-
* This optional callback populates the &struct irq_fwspec for the
100-
* parent's IRQ domain. If this is not specified, then
99+
* This optional callback allocates and populates the specific struct
100+
* for the parent's IRQ domain. If this is not specified, then
101101
* &gpiochip_populate_parent_fwspec_twocell will be used. A four-cell
102102
* variant named &gpiochip_populate_parent_fwspec_fourcell is also
103103
* available.
104104
*/
105-
void (*populate_parent_fwspec)(struct gpio_chip *chip,
106-
struct irq_fwspec *fwspec,
105+
void *(*populate_parent_alloc_arg)(struct gpio_chip *chip,
107106
unsigned int parent_hwirq,
108107
unsigned int parent_type);
109108

@@ -537,26 +536,22 @@ struct bgpio_pdata {
537536

538537
#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
539538

540-
void gpiochip_populate_parent_fwspec_twocell(struct gpio_chip *chip,
541-
struct irq_fwspec *fwspec,
539+
void *gpiochip_populate_parent_fwspec_twocell(struct gpio_chip *chip,
542540
unsigned int parent_hwirq,
543541
unsigned int parent_type);
544-
void gpiochip_populate_parent_fwspec_fourcell(struct gpio_chip *chip,
545-
struct irq_fwspec *fwspec,
542+
void *gpiochip_populate_parent_fwspec_fourcell(struct gpio_chip *chip,
546543
unsigned int parent_hwirq,
547544
unsigned int parent_type);
548545

549546
#else
550547

551-
static inline void gpiochip_populate_parent_fwspec_twocell(struct gpio_chip *chip,
552-
struct irq_fwspec *fwspec,
548+
static inline void *gpiochip_populate_parent_fwspec_twocell(struct gpio_chip *chip,
553549
unsigned int parent_hwirq,
554550
unsigned int parent_type)
555551
{
556552
}
557553

558-
static inline void gpiochip_populate_parent_fwspec_fourcell(struct gpio_chip *chip,
559-
struct irq_fwspec *fwspec,
554+
static inline void *gpiochip_populate_parent_fwspec_fourcell(struct gpio_chip *chip,
560555
unsigned int parent_hwirq,
561556
unsigned int parent_type)
562557
{

0 commit comments

Comments
 (0)