static int bcm_kona_gpio_probe()

in gpio-bcm-kona.c [564:663]


static int bcm_kona_gpio_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	const struct of_device_id *match;
	struct bcm_kona_gpio_bank *bank;
	struct bcm_kona_gpio *kona_gpio;
	struct gpio_chip *chip;
	int ret;
	int i;

	match = of_match_device(bcm_kona_gpio_of_match, dev);
	if (!match) {
		dev_err(dev, "Failed to find gpio controller\n");
		return -ENODEV;
	}

	kona_gpio = devm_kzalloc(dev, sizeof(*kona_gpio), GFP_KERNEL);
	if (!kona_gpio)
		return -ENOMEM;

	kona_gpio->gpio_chip = template_chip;
	chip = &kona_gpio->gpio_chip;
	ret = platform_irq_count(pdev);
	if (!ret) {
		dev_err(dev, "Couldn't determine # GPIO banks\n");
		return -ENOENT;
	} else if (ret < 0) {
		return dev_err_probe(dev, ret, "Couldn't determine GPIO banks\n");
	}
	kona_gpio->num_bank = ret;

	if (kona_gpio->num_bank > GPIO_MAX_BANK_NUM) {
		dev_err(dev, "Too many GPIO banks configured (max=%d)\n",
			GPIO_MAX_BANK_NUM);
		return -ENXIO;
	}
	kona_gpio->banks = devm_kcalloc(dev,
					kona_gpio->num_bank,
					sizeof(*kona_gpio->banks),
					GFP_KERNEL);
	if (!kona_gpio->banks)
		return -ENOMEM;

	kona_gpio->pdev = pdev;
	platform_set_drvdata(pdev, kona_gpio);
	chip->parent = dev;
	chip->ngpio = kona_gpio->num_bank * GPIO_PER_BANK;

	kona_gpio->irq_domain = irq_domain_add_linear(dev->of_node,
						      chip->ngpio,
						      &bcm_kona_irq_ops,
						      kona_gpio);
	if (!kona_gpio->irq_domain) {
		dev_err(dev, "Couldn't allocate IRQ domain\n");
		return -ENXIO;
	}

	kona_gpio->reg_base = devm_platform_ioremap_resource(pdev, 0);
	if (IS_ERR(kona_gpio->reg_base)) {
		ret = PTR_ERR(kona_gpio->reg_base);
		goto err_irq_domain;
	}

	for (i = 0; i < kona_gpio->num_bank; i++) {
		bank = &kona_gpio->banks[i];
		bank->id = i;
		bank->irq = platform_get_irq(pdev, i);
		bank->kona_gpio = kona_gpio;
		if (bank->irq < 0) {
			dev_err(dev, "Couldn't get IRQ for bank %d", i);
			ret = -ENOENT;
			goto err_irq_domain;
		}
	}

	dev_info(&pdev->dev, "Setting up Kona GPIO\n");

	bcm_kona_gpio_reset(kona_gpio);

	ret = devm_gpiochip_add_data(dev, chip, kona_gpio);
	if (ret < 0) {
		dev_err(dev, "Couldn't add GPIO chip -- %d\n", ret);
		goto err_irq_domain;
	}
	for (i = 0; i < kona_gpio->num_bank; i++) {
		bank = &kona_gpio->banks[i];
		irq_set_chained_handler_and_data(bank->irq,
						 bcm_kona_gpio_irq_handler,
						 bank);
	}

	raw_spin_lock_init(&kona_gpio->lock);

	return 0;

err_irq_domain:
	irq_domain_remove(kona_gpio->irq_domain);

	return ret;
}