qcom: spmi-gpio: convert to hierarchical IRQ helpers in gpio core

Now that the GPIO core has support for hierarchical IRQ chips, convert
Qualcomm's spmi-gpio over to use these new helpers to reduce duplicated
code across drivers.

This change was tested on a LG Nexus 5 (hammerhead) phone.

Signed-off-by: Brian Masney <masneyb@onstation.org>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Link: https://lore.kernel.org/r/20190808123242.5359-3-linus.walleij@linaro.org
This commit is contained in:
Brian Masney 2019-08-08 14:32:39 +02:00 committed by Linus Walleij
parent aa7d618ac6
commit 821c76c4c3
2 changed files with 27 additions and 68 deletions

View File

@ -138,6 +138,7 @@ config PINCTRL_QCOM_SPMI_PMIC
select PINMUX select PINMUX
select PINCONF select PINCONF
select GENERIC_PINCONF select GENERIC_PINCONF
select GPIOLIB_IRQCHIP
select IRQ_DOMAIN_HIERARCHY select IRQ_DOMAIN_HIERARCHY
help help
This is the pinctrl, pinmux, pinconf and gpiolib driver for the This is the pinctrl, pinmux, pinconf and gpiolib driver for the

View File

@ -170,8 +170,6 @@ struct pmic_gpio_state {
struct regmap *map; struct regmap *map;
struct pinctrl_dev *ctrl; struct pinctrl_dev *ctrl;
struct gpio_chip chip; struct gpio_chip chip;
struct fwnode_handle *fwnode;
struct irq_domain *domain;
}; };
static const struct pinconf_generic_params pmic_gpio_bindings[] = { static const struct pinconf_generic_params pmic_gpio_bindings[] = {
@ -751,23 +749,6 @@ static int pmic_gpio_of_xlate(struct gpio_chip *chip,
return gpio_desc->args[0] - PMIC_GPIO_PHYSICAL_OFFSET; return gpio_desc->args[0] - PMIC_GPIO_PHYSICAL_OFFSET;
} }
static int pmic_gpio_to_irq(struct gpio_chip *chip, unsigned pin)
{
struct pmic_gpio_state *state = gpiochip_get_data(chip);
struct irq_fwspec fwspec;
fwspec.fwnode = state->fwnode;
fwspec.param_count = 2;
fwspec.param[0] = pin + PMIC_GPIO_PHYSICAL_OFFSET;
/*
* Set the type to a safe value temporarily. This will be overwritten
* later with the proper value by irq_set_type.
*/
fwspec.param[1] = IRQ_TYPE_EDGE_RISING;
return irq_create_fwspec_mapping(&fwspec);
}
static void pmic_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) static void pmic_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
{ {
struct pmic_gpio_state *state = gpiochip_get_data(chip); struct pmic_gpio_state *state = gpiochip_get_data(chip);
@ -787,7 +768,6 @@ static const struct gpio_chip pmic_gpio_gpio_template = {
.request = gpiochip_generic_request, .request = gpiochip_generic_request,
.free = gpiochip_generic_free, .free = gpiochip_generic_free,
.of_xlate = pmic_gpio_of_xlate, .of_xlate = pmic_gpio_of_xlate,
.to_irq = pmic_gpio_to_irq,
.dbg_show = pmic_gpio_dbg_show, .dbg_show = pmic_gpio_dbg_show,
}; };
@ -964,45 +944,23 @@ static int pmic_gpio_domain_translate(struct irq_domain *domain,
return 0; return 0;
} }
static int pmic_gpio_domain_alloc(struct irq_domain *domain, unsigned int virq, static unsigned int pmic_gpio_child_offset_to_irq(struct gpio_chip *chip,
unsigned int nr_irqs, void *data) unsigned int offset)
{ {
struct pmic_gpio_state *state = container_of(domain->host_data, return offset + PMIC_GPIO_PHYSICAL_OFFSET;
struct pmic_gpio_state,
chip);
struct irq_fwspec *fwspec = data;
struct irq_fwspec parent_fwspec;
irq_hw_number_t hwirq;
unsigned int type;
int ret, i;
ret = pmic_gpio_domain_translate(domain, fwspec, &hwirq, &type);
if (ret)
return ret;
for (i = 0; i < nr_irqs; i++)
irq_domain_set_info(domain, virq + i, hwirq + i,
&pmic_gpio_irq_chip, state,
handle_level_irq, NULL, NULL);
parent_fwspec.fwnode = domain->parent->fwnode;
parent_fwspec.param_count = 4;
parent_fwspec.param[0] = 0;
parent_fwspec.param[1] = hwirq + 0xc0;
parent_fwspec.param[2] = 0;
parent_fwspec.param[3] = fwspec->param[1];
return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs,
&parent_fwspec);
} }
static const struct irq_domain_ops pmic_gpio_domain_ops = { static int pmic_gpio_child_to_parent_hwirq(struct gpio_chip *chip,
.activate = gpiochip_irq_domain_activate, unsigned int child_hwirq,
.alloc = pmic_gpio_domain_alloc, unsigned int child_type,
.deactivate = gpiochip_irq_domain_deactivate, unsigned int *parent_hwirq,
.free = irq_domain_free_irqs_common, unsigned int *parent_type)
.translate = pmic_gpio_domain_translate, {
}; *parent_hwirq = child_hwirq + 0xc0;
*parent_type = child_type;
return 0;
}
static int pmic_gpio_probe(struct platform_device *pdev) static int pmic_gpio_probe(struct platform_device *pdev)
{ {
@ -1013,6 +971,7 @@ static int pmic_gpio_probe(struct platform_device *pdev)
struct pinctrl_desc *pctrldesc; struct pinctrl_desc *pctrldesc;
struct pmic_gpio_pad *pad, *pads; struct pmic_gpio_pad *pad, *pads;
struct pmic_gpio_state *state; struct pmic_gpio_state *state;
struct gpio_irq_chip *girq;
int ret, npins, i; int ret, npins, i;
u32 reg; u32 reg;
@ -1092,19 +1051,21 @@ static int pmic_gpio_probe(struct platform_device *pdev)
if (!parent_domain) if (!parent_domain)
return -ENXIO; return -ENXIO;
state->fwnode = of_node_to_fwnode(state->dev->of_node); girq = &state->chip.irq;
state->domain = irq_domain_create_hierarchy(parent_domain, 0, girq->chip = &pmic_gpio_irq_chip;
state->chip.ngpio, girq->default_type = IRQ_TYPE_NONE;
state->fwnode, girq->handler = handle_level_irq;
&pmic_gpio_domain_ops, girq->fwnode = of_node_to_fwnode(state->dev->of_node);
&state->chip); girq->parent_domain = parent_domain;
if (!state->domain) girq->child_to_parent_hwirq = pmic_gpio_child_to_parent_hwirq;
return -ENODEV; girq->populate_parent_fwspec = 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;
ret = gpiochip_add_data(&state->chip, state); ret = gpiochip_add_data(&state->chip, state);
if (ret) { if (ret) {
dev_err(state->dev, "can't add gpio chip\n"); dev_err(state->dev, "can't add gpio chip\n");
goto err_chip_add_data; return ret;
} }
/* /*
@ -1130,8 +1091,6 @@ static int pmic_gpio_probe(struct platform_device *pdev)
err_range: err_range:
gpiochip_remove(&state->chip); gpiochip_remove(&state->chip);
err_chip_add_data:
irq_domain_remove(state->domain);
return ret; return ret;
} }
@ -1140,7 +1099,6 @@ static int pmic_gpio_remove(struct platform_device *pdev)
struct pmic_gpio_state *state = platform_get_drvdata(pdev); struct pmic_gpio_state *state = platform_get_drvdata(pdev);
gpiochip_remove(&state->chip); gpiochip_remove(&state->chip);
irq_domain_remove(state->domain);
return 0; return 0;
} }