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;
}