static int stm32_exti_probe()

in irq-stm32-exti.c [845:920]


static int stm32_exti_probe(struct platform_device *pdev)
{
	int ret, i;
	struct device *dev = &pdev->dev;
	struct device_node *np = dev->of_node;
	struct irq_domain *parent_domain, *domain;
	struct stm32_exti_host_data *host_data;
	const struct stm32_exti_drv_data *drv_data;

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

	/* check for optional hwspinlock which may be not available yet */
	ret = of_hwspin_lock_get_id(np, 0);
	if (ret == -EPROBE_DEFER)
		/* hwspinlock framework not yet ready */
		return ret;

	if (ret >= 0) {
		host_data->hwlock = devm_hwspin_lock_request_specific(dev, ret);
		if (!host_data->hwlock) {
			dev_err(dev, "Failed to request hwspinlock\n");
			return -EINVAL;
		}
	} else if (ret != -ENOENT) {
		/* note: ENOENT is a valid case (means 'no hwspinlock') */
		dev_err(dev, "Failed to get hwspinlock\n");
		return ret;
	}

	/* initialize host_data */
	drv_data = of_device_get_match_data(dev);
	if (!drv_data) {
		dev_err(dev, "no of match data\n");
		return -ENODEV;
	}
	host_data->drv_data = drv_data;

	host_data->chips_data = devm_kcalloc(dev, drv_data->bank_nr,
					     sizeof(*host_data->chips_data),
					     GFP_KERNEL);
	if (!host_data->chips_data)
		return -ENOMEM;

	host_data->base = devm_platform_ioremap_resource(pdev, 0);
	if (IS_ERR(host_data->base))
		return PTR_ERR(host_data->base);

	for (i = 0; i < drv_data->bank_nr; i++)
		stm32_exti_chip_init(host_data, i, np);

	parent_domain = irq_find_host(of_irq_find_parent(np));
	if (!parent_domain) {
		dev_err(dev, "GIC interrupt-parent not found\n");
		return -EINVAL;
	}

	domain = irq_domain_add_hierarchy(parent_domain, 0,
					  drv_data->bank_nr * IRQS_PER_BANK,
					  np, &stm32_exti_h_domain_ops,
					  host_data);

	if (!domain) {
		dev_err(dev, "Could not register exti domain\n");
		return -ENOMEM;
	}

	ret = devm_add_action_or_reset(dev, stm32_exti_remove_irq, domain);
	if (ret)
		return ret;

	stm32_exti_h_syscore_init(host_data);

	return 0;
}