diff options
Diffstat (limited to 'target/linux/leon/patches-2.6.36/009-remove_second_timer.patch')
-rw-r--r-- | target/linux/leon/patches-2.6.36/009-remove_second_timer.patch | 187 |
1 files changed, 187 insertions, 0 deletions
diff --git a/target/linux/leon/patches-2.6.36/009-remove_second_timer.patch b/target/linux/leon/patches-2.6.36/009-remove_second_timer.patch new file mode 100644 index 0000000..b0b1346 --- /dev/null +++ b/target/linux/leon/patches-2.6.36/009-remove_second_timer.patch @@ -0,0 +1,187 @@ +From 300f3ee36c3019ee36f81befd91cd1b32544cefe Mon Sep 17 00:00:00 2001 +From: Daniel Hellstrom <daniel@gaisler.com> +Date: Wed, 22 Sep 2010 15:39:05 +0200 +Subject: [PATCH] SPARC/LEON: Removed the need for two timers, per-cpu ticker is shared with system clock timer. + +Signed-off-by: Daniel Hellstrom <daniel@gaisler.com> +--- + arch/sparc/include/asm/leon.h | 2 +- + arch/sparc/include/asm/leon_amba.h | 3 +- + arch/sparc/kernel/entry.S | 3 +- + arch/sparc/kernel/leon_kernel.c | 37 ++++++++--------------------------- + arch/sparc/kernel/leon_smp.c | 8 ++++++- + 5 files changed, 21 insertions(+), 32 deletions(-) + +--- a/arch/sparc/include/asm/leon.h ++++ b/arch/sparc/include/asm/leon.h +@@ -240,7 +240,7 @@ static inline int sparc_leon3_cpuid(void + + #ifdef CONFIG_SMP + # define LEON3_IRQ_RESCHEDULE 13 +-# define LEON3_IRQ_TICKER (leon_percpu_timer_dev[0].irq) ++# define LEON3_IRQ_TICKER (leon3_gptimer_irq + leon3_gptimer_idx) + # define LEON3_IRQ_CROSS_CALL 15 + #endif + +--- a/arch/sparc/include/asm/leon_amba.h ++++ b/arch/sparc/include/asm/leon_amba.h +@@ -182,11 +182,12 @@ void _amba_init(struct device_node *dp, + + extern struct leon3_irqctrl_regs_map *leon3_irqctrl_regs; + extern struct leon3_gptimer_regs_map *leon3_gptimer_regs; +-extern struct amba_apb_device leon_percpu_timer_dev[16]; + extern int leondebug_irq_disable; + extern int leon_debug_irqout; + extern unsigned long leon3_gptimer_irq; ++extern unsigned long leon3_gptimer_idx; /* Timer Index (starting at 0) with Timer Core */ + extern unsigned int sparc_leon_eirq; ++extern unsigned long leon3_cpu_idx; + + #endif /* __ASSEMBLY__ */ + +--- a/arch/sparc/kernel/entry.S ++++ b/arch/sparc/kernel/entry.S +@@ -411,8 +411,9 @@ smpleon_ticker: + WRITE_PAUSE + wr %g2, PSR_ET, %psr + WRITE_PAUSE ++ mov %l7, %o0 ! irq level + call leon_percpu_timer_interrupt +- add %sp, STACKFRAME_SZ, %o0 ++ add %sp, STACKFRAME_SZ, %o1 ! pt_regs + wr %l0, PSR_ET, %psr + WRITE_PAUSE + RESTORE_ALL +--- a/arch/sparc/kernel/leon_kernel.c ++++ b/arch/sparc/kernel/leon_kernel.c +@@ -25,7 +25,6 @@ + + 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; +@@ -34,6 +33,7 @@ static int dummy_master_l10_counter; + 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; ++unsigned long leon3_cpu_idx = 0; /* Boot CPU Index */ + #define LEON_IMASK ((&leon3_irqctrl_regs->mask[0])) + + /* Return the IRQ of the pending IRQ on the extended IRQ controller */ +@@ -109,13 +109,14 @@ void __init leon_init_timers(irq_handler + struct device_node *rootnp, *np; + struct property *pp; + int len; +- int cpu, icsel; ++ int icsel; + int ampopts; + + leondebug_irq_disable = 0; + leon_debug_irqout = 0; + master_l10_counter = (unsigned int *)&dummy_master_l10_counter; + dummy_master_l10_counter = 0; ++ leon3_cpu_idx = sparc_leon3_cpuid(); + + /* Find IRQMP IRQ Controller Registers base address otherwise bail out. */ + rootnp = of_find_node_by_path("/ambapp0"); +@@ -152,21 +153,11 @@ void __init leon_init_timers(irq_handler + (((1000000 / HZ) - 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+leon3_gptimer_idx; +- + if (!(LEON3_BYPASS_LOAD_PA(&leon3_gptimer_regs->config) & + (1<<LEON3_GPTIMER_SEPIRQ))) { +- prom_printf("irq timer not configured with separate irqs\n"); +- BUG(); ++ prom_printf("LEON-SMP: GPTIMER use shared irqs, using other timers will fail.\n"); + } + +- 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 / HZ) - 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 + * IRQ controllers, each mapped on a 4Kb boundary. + * Each CPU may be routed to different IRQCTRLs, however +@@ -175,9 +166,8 @@ void __init leon_init_timers(irq_handler + * accessed anyway. + * In AMP systems, Linux may not be run on CPU0. + */ +- cpu = sparc_leon3_cpuid(); +- icsel = LEON3_BYPASS_LOAD_PA(&leon3_irqctrl_regs->icsel[cpu/8]); +- icsel = (icsel >> ((7 - (cpu&0x7)) * 4)) & 0xf; ++ icsel = LEON3_BYPASS_LOAD_PA(&leon3_irqctrl_regs->icsel[leon3_cpu_idx/8]); ++ icsel = (icsel >> ((7 - (leon3_cpu_idx & 0x7)) * 4)) & 0xf; + leon3_irqctrl_regs += icsel; + + LEON3_BYPASS_STORE_PA(&(leon3_irqctrl_regs->mask[0]), 0); +@@ -204,7 +194,8 @@ void __init leon_init_timers(irq_handler + # ifdef CONFIG_SMP + { + unsigned long flags; +- struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (leon_percpu_timer_dev[0].irq - 1)]; ++ struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + ++ (leon3_gptimer_irq + leon3_gptimer_idx - 1)]; + + /* For SMP we use the level 14 ticker, however the bootup code + * has copied the firmwares level 14 vector into boot cpu's +@@ -222,21 +213,11 @@ void __init leon_init_timers(irq_handler + } + # endif + +- if (leon3_gptimer_regs) { +- LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].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[leon3_gptimer_idx+1].ctrl, +- LEON3_GPTIMER_EN | +- LEON3_GPTIMER_RL | +- LEON3_GPTIMER_LD | +- LEON3_GPTIMER_IRQEN); +-#endif +- +- } + } + + void leon_clear_clock_irq(void) +--- a/arch/sparc/kernel/leon_smp.c ++++ b/arch/sparc/kernel/leon_smp.c +@@ -52,6 +52,7 @@ extern volatile unsigned long cpu_callin + extern unsigned char boot_cpu_id; + extern cpumask_t smp_commenced_mask; + void __init leon_configure_cache_smp(void); ++extern void handler_irq(int irq, struct pt_regs * regs); + + static inline unsigned long do_swap(volatile unsigned long *ptr, + unsigned long val) +@@ -385,7 +386,7 @@ void leon_cross_call_irq(void) + ccall_info.processors_out[i] = 1; + } + +-void leon_percpu_timer_interrupt(struct pt_regs *regs) ++void leon_percpu_timer_interrupt(int irq, struct pt_regs *regs) + { + struct pt_regs *old_regs; + int cpu = smp_processor_id(); +@@ -406,6 +407,11 @@ void leon_percpu_timer_interrupt(struct + prof_counter(cpu) = prof_multiplier(cpu); + } + set_irq_regs(old_regs); ++ ++ if ( cpu == leon3_cpu_idx ) { ++ /* Ticker Clock is shared with the System Clock */ ++ handler_irq(irq, regs); ++ } + } + + static void __init smp_setup_percpu_timer(void) |