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) ACKed when the CPU takes the trap.
*/ 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 the Extended IRQ, the IRQs routed through the Ext-IRQ * controller have a mask-bit of their own, so this is safe.
*/
irq_link(veirq);
mask = 1 << eirq;
oldmask = LEON3_BYPASS_LOAD_PA(LEON_IMASK(boot_cpu_id));
LEON3_BYPASS_STORE_PA(LEON_IMASK(boot_cpu_id), (oldmask | mask));
sparc_leon_eirq = eirq;
}
/* 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;
/* * The IRQ controller may (if implemented) consist of multiple * IRQ controllers, each mapped on a 4Kb boundary. * Each CPU may be routed to different IRQCTRLs, however * we assume that all CPUs (in SMP system) is routed to the * same IRQ Controller, and for non-SMP only one IRQCTRL is * accessed anyway. * In AMP systems, Linux must run on CPU0 for the time being.
*/
icsel = LEON3_BYPASS_LOAD_PA(&leon3_irqctrl_regs->icsel[boot_cpu_id/8]);
icsel = (icsel >> ((7 - (boot_cpu_id&0x7)) * 4)) & 0xf;
leon3_irqctrl_regs += icsel;
/* Mask all IRQs on boot-cpu IRQ controller */
LEON3_BYPASS_STORE_PA(&leon3_irqctrl_regs->mask[boot_cpu_id], 0);
/* * In SMP, sun4m adds a IPI handler to IRQ trap handler that * LEON never must take, sun4d and LEON overwrites the branch * with a NOP.
*/
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.