static int at91_gpio_probe()

in pinctrl-at91.c [1814:1927]


static int at91_gpio_probe(struct platform_device *pdev)
{
	struct device_node *np = pdev->dev.of_node;
	struct at91_gpio_chip *at91_chip = NULL;
	struct gpio_chip *chip;
	struct pinctrl_gpio_range *range;
	int ret = 0;
	int irq, i;
	int alias_idx = of_alias_get_id(np, "gpio");
	uint32_t ngpio;
	char **names;

	BUG_ON(alias_idx >= ARRAY_SIZE(gpio_chips));
	if (gpio_chips[alias_idx]) {
		ret = -EBUSY;
		goto err;
	}

	irq = platform_get_irq(pdev, 0);
	if (irq < 0) {
		ret = irq;
		goto err;
	}

	at91_chip = devm_kzalloc(&pdev->dev, sizeof(*at91_chip), GFP_KERNEL);
	if (!at91_chip) {
		ret = -ENOMEM;
		goto err;
	}

	at91_chip->regbase = devm_platform_ioremap_resource(pdev, 0);
	if (IS_ERR(at91_chip->regbase)) {
		ret = PTR_ERR(at91_chip->regbase);
		goto err;
	}

	at91_chip->ops = (const struct at91_pinctrl_mux_ops *)
		of_match_device(at91_gpio_of_match, &pdev->dev)->data;
	at91_chip->pioc_virq = irq;
	at91_chip->pioc_idx = alias_idx;

	at91_chip->clock = devm_clk_get(&pdev->dev, NULL);
	if (IS_ERR(at91_chip->clock)) {
		dev_err(&pdev->dev, "failed to get clock, ignoring.\n");
		ret = PTR_ERR(at91_chip->clock);
		goto err;
	}

	ret = clk_prepare_enable(at91_chip->clock);
	if (ret) {
		dev_err(&pdev->dev, "failed to prepare and enable clock, ignoring.\n");
		goto clk_enable_err;
	}

	at91_chip->chip = at91_gpio_template;

	chip = &at91_chip->chip;
	chip->label = dev_name(&pdev->dev);
	chip->parent = &pdev->dev;
	chip->owner = THIS_MODULE;
	chip->base = alias_idx * MAX_NB_GPIO_PER_BANK;

	if (!of_property_read_u32(np, "#gpio-lines", &ngpio)) {
		if (ngpio >= MAX_NB_GPIO_PER_BANK)
			pr_err("at91_gpio.%d, gpio-nb >= %d failback to %d\n",
			       alias_idx, MAX_NB_GPIO_PER_BANK, MAX_NB_GPIO_PER_BANK);
		else
			chip->ngpio = ngpio;
	}

	names = devm_kcalloc(&pdev->dev, chip->ngpio, sizeof(char *),
			     GFP_KERNEL);

	if (!names) {
		ret = -ENOMEM;
		goto clk_enable_err;
	}

	for (i = 0; i < chip->ngpio; i++)
		names[i] = kasprintf(GFP_KERNEL, "pio%c%d", alias_idx + 'A', i);

	chip->names = (const char *const *)names;

	range = &at91_chip->range;
	range->name = chip->label;
	range->id = alias_idx;
	range->pin_base = range->base = range->id * MAX_NB_GPIO_PER_BANK;

	range->npins = chip->ngpio;
	range->gc = chip;

	ret = at91_gpio_of_irq_setup(pdev, at91_chip);
	if (ret)
		goto gpiochip_add_err;

	ret = gpiochip_add_data(chip, at91_chip);
	if (ret)
		goto gpiochip_add_err;

	gpio_chips[alias_idx] = at91_chip;
	gpio_banks = max(gpio_banks, alias_idx + 1);

	dev_info(&pdev->dev, "at address %p\n", at91_chip->regbase);

	return 0;

gpiochip_add_err:
clk_enable_err:
	clk_disable_unprepare(at91_chip->clock);
err:
	dev_err(&pdev->dev, "Failure %i for GPIO %i\n", ret, alias_idx);

	return ret;
}