struct leon3_irqctrl_regs_map *leon3_irqctrl_regs; /* interrupt controller base address */ struct leon3_gptimer_regs_map *leon3_gptimer_regs; /* timer controller base address */
int leondebug_irq_disable; int leon_debug_irqout; staticvolatile u32 dummy_master_l10_counter; unsignedlong amba_system_id; static DEFINE_SPINLOCK(leon_irq_lock);
staticunsignedlong leon3_gptimer_idx; /* Timer Index (0..6) within Timer Core */ staticunsignedlong leon3_gptimer_ackmask; /* For clearing pending bit */ unsignedlong leon3_gptimer_irq; /* interrupt controller irq number */ unsignedint sparc_leon_eirq; #define LEON_IMASK(cpu) (&leon3_irqctrl_regs->mask[cpu]) #define LEON_IACK (&leon3_irqctrl_regs->iclear) #define LEON_DO_ACK_HW 1
/* Return the last ACKed IRQ by the Extended IRQ controller. It has already *been(automatically)ACKedwhentheCPUtakesthetrap.
*/ staticinlineunsignedint leon_eirq_get(int cpu)
{ return LEON3_BYPASS_LOAD_PA(&leon3_irqctrl_regs->intid[cpu]) & 0x1f;
}
/* Handle one or multiple IRQs from the extended interrupt controller */ staticvoid leon_handle_ext_irq(struct irq_desc *desc)
{ unsignedint eirq; struct irq_bucket *p; int cpu = sparc_leon3_cpuid();
eirq = leon_eirq_get(cpu);
p = irq_map[eirq]; if ((eirq & 0x10) && p && p->irq) /* bit4 tells if IRQ happened */
generic_handle_irq(p->irq);
}
/* The extended IRQ controller has been found, this function registers it */ staticvoid leon_eirq_setup(unsignedint eirq)
{ unsignedlong mask, oldmask; unsignedint veirq;
if (eirq < 1 || eirq > 0xf) {
printk(KERN_ERR "LEON EXT IRQ NUMBER BAD: %d\n", eirq); return;
}
/* unmask on old CPU first before enabling on the selected CPU */
spin_lock_irqsave(&leon_irq_lock, flags);
oldmask = LEON3_BYPASS_LOAD_PA(LEON_IMASK(oldcpu));
LEON3_BYPASS_STORE_PA(LEON_IMASK(oldcpu), (oldmask & ~mask));
oldmask = LEON3_BYPASS_LOAD_PA(LEON_IMASK(newcpu));
LEON3_BYPASS_STORE_PA(LEON_IMASK(newcpu), (oldmask | mask));
spin_unlock_irqrestore(&leon_irq_lock, flags);
out: return IRQ_SET_MASK_OK;
}
rootnp = of_find_node_by_path("/ambapp0"); if (!rootnp) goto bad;
/* Find System ID: GRLIB build ID and optional CHIP ID */
pp = of_find_property(rootnp, "systemid", &len); if (pp)
amba_system_id = *(unsignedlong *)pp->value;
/* Find IRQMP IRQ Controller Registers base adr otherwise bail out */
np = of_find_node_by_name(rootnp, "GAISLER_IRQMP"); if (!np) {
np = of_find_node_by_name(rootnp, "01_00d"); if (!np) goto bad;
}
pp = of_find_property(np, "reg", &len); if (!pp) goto bad;
leon3_irqctrl_regs = *(struct leon3_irqctrl_regs_map **)pp->value;
/* *InSMP,sun4maddsaIPIhandlertoIRQtraphandlerthat *LEONnevermusttake,sun4dandLEONoverwritesthebranch *withaNOP.
*/
local_irq_save(flags);
patchme_maybe_smp_msg[0] = 0x01000000; /* NOP out the branch */
local_ops->cache_all();
local_irq_restore(flags);
} #endif
config = LEON3_BYPASS_LOAD_PA(&leon3_gptimer_regs->config); if (config & (1 << LEON3_GPTIMER_SEPIRQ))
leon3_gptimer_irq += leon3_gptimer_idx; elseif ((config & LEON3_GPTIMER_TIMERS) > 1)
pr_warn("GPTIMER uses shared irqs, using other timers of the same core will fail.\n");
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.