009-remove_second_timer.patch 6.9 KB

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