ret = of_property_read_u32_array(dn , "brcm,int-fwd-mask",
intc->irq_fwd_mask, n_words); if (ret != 0 && ret != -EINVAL) { /* property exists but has the wrong number of words */
pr_err("invalid brcm,int-fwd-mask property\n"); return -EINVAL;
}
cpu = intc->cpus[idx] = kzalloc(struct_size(cpu, mask_cache, n_words),
GFP_KERNEL); if (!cpu) return -ENOMEM;
cpu->map_base = ioremap(res.start, sz); if (!cpu->map_base) return -ENOMEM;
for (i = 0; i < n_words; i++) {
l1_writel(~intc->irq_fwd_mask[i],
cpu->map_base + reg_mask_set(intc, i));
l1_writel(intc->irq_fwd_mask[i],
cpu->map_base + reg_mask_clr(intc, i));
cpu->mask_cache[i] = ~intc->irq_fwd_mask[i];
}
parent_irq = irq_of_parse_and_map(dn, idx); if (!parent_irq) {
pr_err("failed to map parent interrupt %d\n", parent_irq); return -EINVAL;
}
if (of_property_read_bool(dn, "brcm,irq-can-wake"))
enable_irq_wake(parent_irq);
#ifdef CONFIG_PM_SLEEP /* * We keep a list of bcm7038_l1_chip used for suspend/resume. This hack is * used because the struct chip_type suspend/resume hooks are not called * unless chip_type is hooked onto a generic_chip. Since this driver does * not use generic_chip, we need to manually hook our resume/suspend to * syscore_ops.
*/ static LIST_HEAD(bcm7038_l1_intcs_list); static DEFINE_RAW_SPINLOCK(bcm7038_l1_intcs_lock);
/* Wakeup interrupt should only come from the boot cpu */ #ifdefined(CONFIG_SMP) && defined(CONFIG_MIPS)
boot_cpu = cpu_logical_map(0); #else
boot_cpu = 0; #endif
list_for_each_entry(intc, &bcm7038_l1_intcs_list, list) { for (word = 0; word < intc->n_words; word++) {
val = intc->wake_mask[word] | intc->irq_fwd_mask[word];
l1_writel(~val,
intc->cpus[boot_cpu]->map_base + reg_mask_set(intc, word));
l1_writel(val,
intc->cpus[boot_cpu]->map_base + reg_mask_clr(intc, word));
}
}
return 0;
}
staticvoid bcm7038_l1_resume(void)
{ struct bcm7038_l1_chip *intc; int boot_cpu, word;
intc = kzalloc(sizeof(*intc), GFP_KERNEL); if (!intc) return -ENOMEM;
raw_spin_lock_init(&intc->lock);
for_each_possible_cpu(idx) {
ret = bcm7038_l1_init_one(dn, idx, intc); if (ret < 0) { if (idx) break;
pr_err("failed to remap intc L1 registers\n"); goto out_free;
}
}
intc->domain = irq_domain_create_linear(of_fwnode_handle(dn), IRQS_PER_WORD * intc->n_words,
&bcm7038_l1_domain_ops,
intc); if (!intc->domain) {
ret = -ENOMEM; goto out_unmap;
}
#ifdef CONFIG_PM_SLEEP /* Add bcm7038_l1_chip into a list */
raw_spin_lock(&bcm7038_l1_intcs_lock);
list_add_tail(&intc->list, &bcm7038_l1_intcs_list);
raw_spin_unlock(&bcm7038_l1_intcs_lock);
if (list_is_singular(&bcm7038_l1_intcs_list))
register_syscore_ops(&bcm7038_l1_syscore_ops); #endif
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.