static int __init imx_gpcv2_irqchip_init()

in irq-imx-gpcv2.c [202:287]


static int __init imx_gpcv2_irqchip_init(struct device_node *node,
			       struct device_node *parent)
{
	struct irq_domain *parent_domain, *domain;
	struct gpcv2_irqchip_data *cd;
	const struct of_device_id *id;
	unsigned long core_num;
	int i;

	if (!parent) {
		pr_err("%pOF: no parent, giving up\n", node);
		return -ENODEV;
	}

	id = of_match_node(gpcv2_of_match, node);
	if (!id) {
		pr_err("%pOF: unknown compatibility string\n", node);
		return -ENODEV;
	}

	core_num = (unsigned long)id->data;

	parent_domain = irq_find_host(parent);
	if (!parent_domain) {
		pr_err("%pOF: unable to get parent domain\n", node);
		return -ENXIO;
	}

	cd = kzalloc(sizeof(struct gpcv2_irqchip_data), GFP_KERNEL);
	if (!cd)
		return -ENOMEM;

	raw_spin_lock_init(&cd->rlock);

	cd->gpc_base = of_iomap(node, 0);
	if (!cd->gpc_base) {
		pr_err("%pOF: unable to map gpc registers\n", node);
		kfree(cd);
		return -ENOMEM;
	}

	domain = irq_domain_add_hierarchy(parent_domain, 0, GPC_MAX_IRQS,
				node, &gpcv2_irqchip_data_domain_ops, cd);
	if (!domain) {
		iounmap(cd->gpc_base);
		kfree(cd);
		return -ENOMEM;
	}
	irq_set_default_host(domain);

	/* Initially mask all interrupts */
	for (i = 0; i < IMR_NUM; i++) {
		void __iomem *reg = cd->gpc_base + i * 4;

		switch (core_num) {
		case 4:
			writel_relaxed(~0, reg + GPC_IMR1_CORE2);
			writel_relaxed(~0, reg + GPC_IMR1_CORE3);
			fallthrough;
		case 2:
			writel_relaxed(~0, reg + GPC_IMR1_CORE0);
			writel_relaxed(~0, reg + GPC_IMR1_CORE1);
		}
		cd->wakeup_sources[i] = ~0;
	}

	/* Let CORE0 as the default CPU to wake up by GPC */
	cd->cpu2wakeup = GPC_IMR1_CORE0;

	/*
	 * Due to hardware design failure, need to make sure GPR
	 * interrupt(#32) is unmasked during RUN mode to avoid entering
	 * DSM by mistake.
	 */
	writel_relaxed(~0x1, cd->gpc_base + cd->cpu2wakeup);

	imx_gpcv2_instance = cd;
	register_syscore_ops(&imx_gpcv2_syscore_ops);

	/*
	 * Clear the OF_POPULATED flag set in of_irq_init so that
	 * later the GPC power domain driver will not be skipped.
	 */
	of_node_clear_flag(node, OF_POPULATED);
	return 0;
}