[sparc] remove broken flag
[openwrt.git] / target / linux / leon / patches / 009-remove_second_timer.patch
1 From 300f3ee36c3019ee36f81befd91cd1b32544cefe Mon Sep 17 00:00:00 2001
2 From: Daniel Hellstrom <daniel@gaisler.com>
3 Date: Wed, 22 Sep 2010 15:39:05 +0200
4 Subject: [PATCH] SPARC/LEON: Removed the need for two timers, per-cpu ticker is shared with system clock timer.
5
6 Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
7 ---
8  arch/sparc/include/asm/leon.h      |    2 +-
9  arch/sparc/include/asm/leon_amba.h |    3 +-
10  arch/sparc/kernel/entry.S          |    3 +-
11  arch/sparc/kernel/leon_kernel.c    |   37 ++++++++---------------------------
12  arch/sparc/kernel/leon_smp.c       |    8 ++++++-
13  5 files changed, 21 insertions(+), 32 deletions(-)
14
15 --- a/arch/sparc/include/asm/leon.h
16 +++ b/arch/sparc/include/asm/leon.h
17 @@ -240,7 +240,7 @@ static inline int sparc_leon3_cpuid(void
18  
19  #ifdef CONFIG_SMP
20  # define LEON3_IRQ_RESCHEDULE          13
21 -# define LEON3_IRQ_TICKER              (leon_percpu_timer_dev[0].irq)
22 +# define LEON3_IRQ_TICKER              (leon3_gptimer_irq + leon3_gptimer_idx)
23  # define LEON3_IRQ_CROSS_CALL          15
24  #endif
25  
26 --- a/arch/sparc/include/asm/leon_amba.h
27 +++ b/arch/sparc/include/asm/leon_amba.h
28 @@ -182,11 +182,12 @@ void _amba_init(struct device_node *dp,
29  
30  extern struct leon3_irqctrl_regs_map *leon3_irqctrl_regs;
31  extern struct leon3_gptimer_regs_map *leon3_gptimer_regs;
32 -extern struct amba_apb_device leon_percpu_timer_dev[16];
33  extern int leondebug_irq_disable;
34  extern int leon_debug_irqout;
35  extern unsigned long leon3_gptimer_irq;
36 +extern unsigned long leon3_gptimer_idx; /* Timer Index (starting at 0) with Timer Core */
37  extern unsigned int sparc_leon_eirq;
38 +extern unsigned long leon3_cpu_idx;
39  
40  #endif /* __ASSEMBLY__ */
41  
42 --- a/arch/sparc/kernel/entry.S
43 +++ b/arch/sparc/kernel/entry.S
44 @@ -411,8 +411,9 @@ smpleon_ticker:
45         WRITE_PAUSE
46         wr      %g2, PSR_ET, %psr
47         WRITE_PAUSE
48 +       mov     %l7, %o0                ! irq level
49         call    leon_percpu_timer_interrupt
50 -        add    %sp, STACKFRAME_SZ, %o0
51 +        add    %sp, STACKFRAME_SZ, %o1 ! pt_regs
52         wr      %l0, PSR_ET, %psr
53         WRITE_PAUSE
54         RESTORE_ALL
55 --- a/arch/sparc/kernel/leon_kernel.c
56 +++ b/arch/sparc/kernel/leon_kernel.c
57 @@ -25,7 +25,6 @@
58  
59  struct leon3_irqctrl_regs_map *leon3_irqctrl_regs = NULL; /* interrupt controller base address, initialized by amba_init() */
60  struct leon3_gptimer_regs_map *leon3_gptimer_regs = NULL; /* timer controller base address, initialized by amba_init() */
61 -struct amba_apb_device leon_percpu_timer_dev[16];
62  
63  int leondebug_irq_disable;
64  int leon_debug_irqout;
65 @@ -34,6 +33,7 @@ static int dummy_master_l10_counter;
66  unsigned long leon3_gptimer_irq = 0; /* interrupt controller irq number, initialized by amba_init() */
67  unsigned long leon3_gptimer_idx = 0; /* Timer Index (starting at 0) with Timer Core */
68  unsigned int sparc_leon_eirq;
69 +unsigned long leon3_cpu_idx = 0; /* Boot CPU Index */
70  #define LEON_IMASK ((&leon3_irqctrl_regs->mask[0]))
71  
72  /* Return the IRQ of the pending IRQ on the extended IRQ controller */
73 @@ -109,13 +109,14 @@ void __init leon_init_timers(irq_handler
74         struct device_node *rootnp, *np;
75         struct property *pp;
76         int len;
77 -       int cpu, icsel;
78 +       int icsel;
79         int ampopts;
80  
81         leondebug_irq_disable = 0;
82         leon_debug_irqout = 0;
83         master_l10_counter = (unsigned int *)&dummy_master_l10_counter;
84         dummy_master_l10_counter = 0;
85 +       leon3_cpu_idx = sparc_leon3_cpuid();
86  
87         /* Find IRQMP IRQ Controller Registers base address otherwise bail out. */
88         rootnp = of_find_node_by_path("/ambapp0");
89 @@ -152,21 +153,11 @@ void __init leon_init_timers(irq_handler
90                                       (((1000000 / HZ) - 1)));
91                 LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl, 0);
92  
93 -#ifdef CONFIG_SMP
94 -               leon_percpu_timer_dev[0].start = (int)leon3_gptimer_regs;
95 -               leon_percpu_timer_dev[0].irq = leon3_gptimer_irq+1+leon3_gptimer_idx;
96 -
97                 if (!(LEON3_BYPASS_LOAD_PA(&leon3_gptimer_regs->config) &
98                       (1<<LEON3_GPTIMER_SEPIRQ))) {
99 -                       prom_printf("irq timer not configured with separate irqs\n");
100 -                       BUG();
101 +                       prom_printf("LEON-SMP: GPTIMER use shared irqs, using other timers will fail.\n");
102                 }
103  
104 -               LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].val, 0);
105 -               LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].rld, (((1000000 / HZ) - 1)));
106 -               LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].ctrl, 0);
107 -# endif
108 -
109                 /* The IRQ controller may (if implemented) consist of multiple
110                  * IRQ controllers, each mapped on a 4Kb boundary.
111                  * Each CPU may be routed to different IRQCTRLs, however
112 @@ -175,9 +166,8 @@ void __init leon_init_timers(irq_handler
113                  * accessed anyway.
114                  * In AMP systems, Linux may not be run on CPU0.
115                  */
116 -               cpu = sparc_leon3_cpuid();
117 -               icsel = LEON3_BYPASS_LOAD_PA(&leon3_irqctrl_regs->icsel[cpu/8]);
118 -               icsel = (icsel >> ((7 - (cpu&0x7)) * 4)) & 0xf;
119 +               icsel = LEON3_BYPASS_LOAD_PA(&leon3_irqctrl_regs->icsel[leon3_cpu_idx/8]);
120 +               icsel = (icsel >> ((7 - (leon3_cpu_idx & 0x7)) * 4)) & 0xf;
121                 leon3_irqctrl_regs += icsel;
122  
123                 LEON3_BYPASS_STORE_PA(&(leon3_irqctrl_regs->mask[0]), 0);
124 @@ -204,7 +194,8 @@ void __init leon_init_timers(irq_handler
125  # ifdef CONFIG_SMP
126         {
127                 unsigned long flags;
128 -               struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (leon_percpu_timer_dev[0].irq - 1)];
129 +               struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + 
130 +                                               (leon3_gptimer_irq + leon3_gptimer_idx - 1)];
131  
132                 /* For SMP we use the level 14 ticker, however the bootup code
133                  * has copied the firmwares level 14 vector into boot cpu's
134 @@ -222,21 +213,11 @@ void __init leon_init_timers(irq_handler
135         }
136  # endif
137  
138 -       if (leon3_gptimer_regs) {
139 -               LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl,
140 +       LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].ctrl,
141                                       LEON3_GPTIMER_EN |
142                                       LEON3_GPTIMER_RL |
143                                       LEON3_GPTIMER_LD | LEON3_GPTIMER_IRQEN);
144  
145 -#ifdef CONFIG_SMP
146 -               LEON3_BYPASS_STORE_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx+1].ctrl,
147 -                                     LEON3_GPTIMER_EN |
148 -                                     LEON3_GPTIMER_RL |
149 -                                     LEON3_GPTIMER_LD |
150 -                                     LEON3_GPTIMER_IRQEN);
151 -#endif
152 -
153 -       }
154  }
155  
156  void leon_clear_clock_irq(void)
157 --- a/arch/sparc/kernel/leon_smp.c
158 +++ b/arch/sparc/kernel/leon_smp.c
159 @@ -52,6 +52,7 @@ extern volatile unsigned long cpu_callin
160  extern unsigned char boot_cpu_id;
161  extern cpumask_t smp_commenced_mask;
162  void __init leon_configure_cache_smp(void);
163 +extern void handler_irq(int irq, struct pt_regs * regs);
164  
165  static inline unsigned long do_swap(volatile unsigned long *ptr,
166                                     unsigned long val)
167 @@ -385,7 +386,7 @@ void leon_cross_call_irq(void)
168         ccall_info.processors_out[i] = 1;
169  }
170  
171 -void leon_percpu_timer_interrupt(struct pt_regs *regs)
172 +void leon_percpu_timer_interrupt(int irq, struct pt_regs *regs)
173  {
174         struct pt_regs *old_regs;
175         int cpu = smp_processor_id();
176 @@ -406,6 +407,11 @@ void leon_percpu_timer_interrupt(struct
177                 prof_counter(cpu) = prof_multiplier(cpu);
178         }
179         set_irq_regs(old_regs);
180 +
181 +       if ( cpu == leon3_cpu_idx ) {
182 +               /* Ticker Clock is shared with the System Clock */
183 +               handler_irq(irq, regs);
184 +       }
185  }
186  
187  static void __init smp_setup_percpu_timer(void)