in qcom/pinctrl-ssbi-gpio.c [708:835]
static int pm8xxx_gpio_probe(struct platform_device *pdev)
{
struct pm8xxx_pin_data *pin_data;
struct irq_domain *parent_domain;
struct device_node *parent_node;
struct pinctrl_pin_desc *pins;
struct gpio_irq_chip *girq;
struct pm8xxx_gpio *pctrl;
int ret, i;
pctrl = devm_kzalloc(&pdev->dev, sizeof(*pctrl), GFP_KERNEL);
if (!pctrl)
return -ENOMEM;
pctrl->dev = &pdev->dev;
pctrl->npins = (uintptr_t) device_get_match_data(&pdev->dev);
pctrl->regmap = dev_get_regmap(pdev->dev.parent, NULL);
if (!pctrl->regmap) {
dev_err(&pdev->dev, "parent regmap unavailable\n");
return -ENXIO;
}
pctrl->desc = pm8xxx_pinctrl_desc;
pctrl->desc.npins = pctrl->npins;
pins = devm_kcalloc(&pdev->dev,
pctrl->desc.npins,
sizeof(struct pinctrl_pin_desc),
GFP_KERNEL);
if (!pins)
return -ENOMEM;
pin_data = devm_kcalloc(&pdev->dev,
pctrl->desc.npins,
sizeof(struct pm8xxx_pin_data),
GFP_KERNEL);
if (!pin_data)
return -ENOMEM;
for (i = 0; i < pctrl->desc.npins; i++) {
pin_data[i].reg = SSBI_REG_ADDR_GPIO(i);
ret = pm8xxx_pin_populate(pctrl, &pin_data[i]);
if (ret)
return ret;
pins[i].number = i;
pins[i].name = pm8xxx_groups[i];
pins[i].drv_data = &pin_data[i];
}
pctrl->desc.pins = pins;
pctrl->desc.num_custom_params = ARRAY_SIZE(pm8xxx_gpio_bindings);
pctrl->desc.custom_params = pm8xxx_gpio_bindings;
#ifdef CONFIG_DEBUG_FS
pctrl->desc.custom_conf_items = pm8xxx_conf_items;
#endif
pctrl->pctrl = devm_pinctrl_register(&pdev->dev, &pctrl->desc, pctrl);
if (IS_ERR(pctrl->pctrl)) {
dev_err(&pdev->dev, "couldn't register pm8xxx gpio driver\n");
return PTR_ERR(pctrl->pctrl);
}
pctrl->chip = pm8xxx_gpio_template;
pctrl->chip.base = -1;
pctrl->chip.parent = &pdev->dev;
pctrl->chip.of_gpio_n_cells = 2;
pctrl->chip.label = dev_name(pctrl->dev);
pctrl->chip.ngpio = pctrl->npins;
parent_node = of_irq_find_parent(pctrl->dev->of_node);
if (!parent_node)
return -ENXIO;
parent_domain = irq_find_host(parent_node);
of_node_put(parent_node);
if (!parent_domain)
return -ENXIO;
girq = &pctrl->chip.irq;
girq->chip = &pm8xxx_irq_chip;
girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_level_irq;
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_alloc_arg = gpiochip_populate_parent_fwspec_twocell;
girq->child_offset_to_irq = pm8xxx_child_offset_to_irq;
girq->child_irq_domain_ops.translate = pm8xxx_domain_translate;
ret = gpiochip_add_data(&pctrl->chip, pctrl);
if (ret) {
dev_err(&pdev->dev, "failed register gpiochip\n");
return ret;
}
/*
* For DeviceTree-supported systems, the gpio core checks the
* pinctrl's device node for the "gpio-ranges" property.
* If it is present, it takes care of adding the pin ranges
* for the driver. In this case the driver can skip ahead.
*
* In order to remain compatible with older, existing DeviceTree
* files which don't set the "gpio-ranges" property or systems that
* utilize ACPI the driver has to call gpiochip_add_pin_range().
*/
if (!of_property_read_bool(pctrl->dev->of_node, "gpio-ranges")) {
ret = gpiochip_add_pin_range(&pctrl->chip, dev_name(pctrl->dev),
0, 0, pctrl->chip.ngpio);
if (ret) {
dev_err(pctrl->dev, "failed to add pin range\n");
goto unregister_gpiochip;
}
}
platform_set_drvdata(pdev, pctrl);
dev_dbg(&pdev->dev, "Qualcomm pm8xxx gpio driver probed\n");
return 0;
unregister_gpiochip:
gpiochip_remove(&pctrl->chip);
return ret;
}