diff options
Diffstat (limited to 'target/linux/leon/patches-2.6.36/007-amp_timer.patch')
-rw-r--r-- | target/linux/leon/patches-2.6.36/007-amp_timer.patch | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/target/linux/leon/patches-2.6.36/007-amp_timer.patch b/target/linux/leon/patches-2.6.36/007-amp_timer.patch new file mode 100644 index 0000000000..d8d436347f --- /dev/null +++ b/target/linux/leon/patches-2.6.36/007-amp_timer.patch @@ -0,0 +1,120 @@ +From 1dffe06838c26b7c3fc99f9ddb7db78e378f6908 Mon Sep 17 00:00:00 2001 +From: Daniel Hellstrom <daniel@gaisler.com> +Date: Wed, 22 Sep 2010 13:21:13 +0200 +Subject: [PATCH] SPARC/LEON: added support for selecting Timer Core and Timer within core, useful for AMP systems. + +Signed-off-by: Daniel Hellstrom <daniel@gaisler.com> +--- + arch/sparc/kernel/leon_kernel.c | 41 +++++++++++++++++++++++++------------- + 1 files changed, 27 insertions(+), 14 deletions(-) + +--- a/arch/sparc/kernel/leon_kernel.c ++++ b/arch/sparc/kernel/leon_kernel.c +@@ -23,15 +23,16 @@ + #include "prom.h" + #include "irq.h" + +-struct leon3_irqctrl_regs_map *leon3_irqctrl_regs; /* interrupt controller base address, initialized by amba_init() */ +-struct leon3_gptimer_regs_map *leon3_gptimer_regs; /* timer controller base address, initialized by amba_init() */ ++struct leon3_irqctrl_regs_map *leon3_irqctrl_regs = NULL; /* interrupt controller base address, initialized by amba_init() */ ++struct leon3_gptimer_regs_map *leon3_gptimer_regs = NULL; /* timer controller base address, initialized by amba_init() */ + struct amba_apb_device leon_percpu_timer_dev[16]; + + int leondebug_irq_disable; + int leon_debug_irqout; + static int dummy_master_l10_counter; + +-unsigned long leon3_gptimer_irq; /* interrupt controller irq number, initialized by amba_init() */ ++unsigned long leon3_gptimer_irq = 0; /* interrupt controller irq number, initialized by amba_init() */ ++unsigned long leon3_gptimer_idx = 0; /* Timer Index (starting at 0) with Timer Core */ + unsigned int sparc_leon_eirq; + #define LEON_IMASK ((&leon3_irqctrl_regs->mask[0])) + +@@ -109,6 +110,7 @@ void __init leon_init_timers(irq_handler + struct property *pp; + int len; + int cpu, icsel; ++ int ampopts; + + leondebug_irq_disable = 0; + leon_debug_irqout = 0; +@@ -124,24 +126,35 @@ void __init leon_init_timers(irq_handler + } + + /* Find GPTIMER Timer Registers base address otherwise bail out. */ +- if (rootnp && (np=of_find_node_by_name(rootnp, "GAISLER_GPTIMER"))) { ++ np = rootnp; ++ while (np && (np=of_find_node_by_name(np, "GAISLER_GPTIMER"))) { ++ ampopts = 0; ++ pp = of_find_property(np, "ampopts", &len); ++ if ( pp && ((ampopts = *(int *)pp->value) == 0) ) { ++ /* Skip this instance, resource already allocated by other OS */ ++ continue; ++ } ++ /* Select Timer-Instance on Timer Core. Default is zero */ ++ leon3_gptimer_idx = ampopts & 0x7; ++ + pp = of_find_property(np, "reg", &len); + if (pp) + leon3_gptimer_regs = *(struct leon3_gptimer_regs_map **)pp->value; + pp = of_find_property(np, "interrupts", &len); + if (pp) + leon3_gptimer_irq = *(unsigned int *)pp->value; ++ break; + } + + if (leon3_gptimer_regs && leon3_irqctrl_regs && leon3_gptimer_irq) { +- LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].val, 0); +- LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].rld, +- (((1000000 / HZ) - 1))); +- LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].ctrl, 0); ++ LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].val, 0); ++ LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].rld, ++ (((1000000 / 100) - 1))); ++ LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl, 0); + + #ifdef CONFIG_SMP + leon_percpu_timer_dev[0].start = (int)leon3_gptimer_regs; +- leon_percpu_timer_dev[0].irq = leon3_gptimer_irq+1; ++ leon_percpu_timer_dev[0].irq = leon3_gptimer_irq+1+leon3_gptimer_idx; + + if (!(LEON3_BYPASS_LOAD_PA(&leon3_gptimer_regs->config) & + (1<<LEON3_GPTIMER_SEPIRQ))) { +@@ -149,9 +162,9 @@ void __init leon_init_timers(irq_handler + BUG(); + } + +- LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].val, 0); +- LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].rld, (((1000000/HZ) - 1))); +- LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].ctrl, 0); ++ LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].val, 0); ++ LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].rld, (((1000000/100) - 1))); ++ LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].ctrl, 0); + # endif + + /* The IRQ controller may (if implemented) consist of multiple +@@ -178,7 +191,7 @@ void __init leon_init_timers(irq_handler + BUG(); + } + +- irq = request_irq(leon3_gptimer_irq, ++ irq = request_irq(leon3_gptimer_irq+leon3_gptimer_idx, + counter_fn, + (IRQF_DISABLED | SA_STATIC_ALLOC), "timer", NULL); + +@@ -210,13 +223,13 @@ void __init leon_init_timers(irq_handler + # endif + + if (leon3_gptimer_regs) { +- LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[0].ctrl, ++ LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl, + LEON3_GPTIMER_EN | + LEON3_GPTIMER_RL | + LEON3_GPTIMER_LD | LEON3_GPTIMER_IRQEN); + + #ifdef CONFIG_SMP +- LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[1].ctrl, ++ LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].ctrl, + LEON3_GPTIMER_EN | + LEON3_GPTIMER_RL | + LEON3_GPTIMER_LD | |