* [PATCH 1/1] sparc32,leon: GENERIC_CLOCKEVENTS support for SPARC-LEON
@ 2012-03-15 10:33 Konrad Eisele
2012-03-16 22:51 ` Kirill Tkhai
0 siblings, 1 reply; 2+ messages in thread
From: Konrad Eisele @ 2012-03-15 10:33 UTC (permalink / raw)
To: sparclinux
Add GENERIC_CLOCKEVENTS support for SPARC-LEON.
The late_time_init initialization has been moved to
enable overriding it for SPARC-LEON.
Signed-off-by: Konrad Eisele <konrad@gaisler.com>
---
arch/sparc/include/asm/leon.h | 3 +-
arch/sparc/kernel/leon_kernel.c | 189 ++++++++++++++++++++++++++++++++++++++-
arch/sparc/kernel/leon_smp.c | 34 +------
arch/sparc/kernel/time_32.c | 4 +-
4 files changed, 193 insertions(+), 37 deletions(-)
diff --git a/arch/sparc/include/asm/leon.h b/arch/sparc/include/asm/leon.h
index a4e457f..9b9b24f 100644
--- a/arch/sparc/include/asm/leon.h
+++ b/arch/sparc/include/asm/leon.h
@@ -323,7 +323,7 @@ extern void leon_update_virq_handling(unsigned int virq,
const char *name, int do_ack);
extern void leon_clear_clock_irq(void);
extern void leon_load_profile_irq(int cpu, unsigned int limit);
-extern void leon_init_timers(irq_handler_t counter_fn);
+extern void leon_init_timers(void);
extern void leon_clear_clock_irq(void);
extern void leon_load_profile_irq(int cpu, unsigned int limit);
extern void leon_trans_init(struct device_node *dp);
@@ -351,6 +351,7 @@ extern void init_IRQ(void);
extern void cpu_panic(void);
extern int __leon_processor_id(void);
void leon_enable_irq_cpu(unsigned int irq_nr, unsigned int cpu);
+extern void leon_register_percpu_ce(int cpu);
extern irqreturn_t leon_percpu_timer_interrupt(int irq, void *unused);
extern unsigned int real_irq_entry[];
diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c
index a19c8a0..62afe3f 100644
--- a/arch/sparc/kernel/leon_kernel.c
+++ b/arch/sparc/kernel/leon_kernel.c
@@ -10,6 +10,8 @@
#include <linux/of_platform.h>
#include <linux/interrupt.h>
#include <linux/of_device.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
#include <asm/oplib.h>
#include <asm/timer.h>
@@ -27,12 +29,18 @@
struct leon3_irqctrl_regs_map *leon3_irqctrl_regs; /* interrupt controller base address */
struct leon3_gptimer_regs_map *leon3_gptimer_regs; /* timer controller base address */
+static __cacheline_aligned_in_smp DEFINE_SEQLOCK(leon_timer_cs_lock);
+static __volatile__ u64 leon_timer_cs_internal_counter = 0;
int leondebug_irq_disable;
int leon_debug_irqout;
static int dummy_master_l10_counter;
unsigned long amba_system_id;
static DEFINE_SPINLOCK(leon_irq_lock);
+static char leon_timer_cs_enabled = 0;
+#ifndef CONFIG_SMP
+static char leon_timer_ce_enabled = 0;
+#endif
unsigned long leon3_gptimer_irq; /* interrupt controller irq number */
unsigned long leon3_gptimer_idx; /* Timer Index (0..6) within Timer Core */
int leon3_ticker_irq; /* Timer ticker IRQ */
@@ -250,7 +258,177 @@ void leon_update_virq_handling(unsigned int virq,
irq_set_chip_data(virq, (void *)mask);
}
-void __init leon_init_timers(irq_handler_t counter_fn)
+static u32 leon_cycles_offset(void)
+{
+ u32 rld, val, off;
+ rld = LEON3_BYPASS_LOAD_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].rld);
+ val = LEON3_BYPASS_LOAD_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].val);
+ off = rld - val;
+ return rld - val;
+}
+
+static cycle_t leon_timer_cs_read(struct clocksource *cs)
+{
+ unsigned int seq, offset;
+ u64 cycles;
+
+ do {
+ seq = read_seqbegin(&leon_timer_cs_lock);
+ cycles = leon_timer_cs_internal_counter;
+ offset = leon_cycles_offset();
+ } while (read_seqretry(&leon_timer_cs_lock, seq));
+
+ cycles *= timer_cs_period;
+ cycles += offset;
+ return cycles;
+}
+
+static struct clocksource leon_timer_cs = {
+ .name = "grtimer-cs",
+ .rating = 200,
+ .read = leon_timer_cs_read,
+ .mask = CLOCKSOURCE_MASK(32),
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+#ifndef CONFIG_SMP
+
+static void leon_timer_ce_set_mode(enum clock_event_mode mode,
+ struct clock_event_device *evt)
+{
+ switch (mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ case CLOCK_EVT_MODE_RESUME:
+ leon_timer_ce_enabled = 1;
+ break;
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ leon_timer_ce_enabled = 0;
+ break;
+ default:
+ break;
+ }
+ smp_mb();
+}
+
+static struct clock_event_device leon_timer_ce = {
+ .name = "grtimer-ce",
+ .rating = 100,
+ .features = CLOCK_EVT_FEAT_PERIODIC,
+ .set_mode = leon_timer_ce_set_mode,
+ .shift = 32
+};
+
+#endif /* !CONFIG_SMP */
+
+static void __init leon_late_time_init(void)
+{
+ leon_timer_cs_enabled = 1;
+
+ clocksource_register_hz(&leon_timer_cs, 1000000);
+
+#ifdef CONFIG_SMP
+ leon_register_percpu_ce(smp_processor_id());
+#else
+ BUG_ON(smp_processor_id() != boot_cpu_id);
+ leon_timer_ce.cpumask = cpu_possible_mask;
+ leon_timer_ce.mult = div_sc(1000000, NSEC_PER_SEC,
+ leon_timer_ce.shift);
+ clockevents_register_device(&leon_timer_ce);
+#endif /* CONFIG_SMP */
+}
+
+/* clocksource irq, non-smp clockevent */
+irqreturn_t notrace leon_timer_interrupt(int dummy, void *dev_id)
+{
+ if (leon_timer_cs_enabled) {
+ write_seqlock(&leon_timer_cs_lock);
+ leon_timer_cs_internal_counter++;
+ write_sequnlock(&leon_timer_cs_lock);
+ }
+#ifndef CONFIG_SMP
+ if (leon_timer_ce_enabled) {
+ if (leon_timer_ce.event_handler)
+ leon_timer_ce.event_handler(&leon_timer_ce);
+ }
+
+#endif
+ return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_SMP
+
+/* smp clockevent irq */
+irqreturn_t leon_percpu_timer_ce_interrupt(int irq, void *unused)
+{
+ struct clock_event_device *ce;
+ int cpu = smp_processor_id();
+
+ leon_clear_profile_irq(cpu);
+
+ ce = &per_cpu(sparc32_clockevent, cpu);
+
+ irq_enter();
+ if (ce->event_handler)
+ ce->event_handler(ce);
+ irq_exit();
+
+ return IRQ_HANDLED;
+}
+
+static void leon_percpu_ce_setup(enum clock_event_mode mode,
+ struct clock_event_device *evt)
+{
+ int cpu = __first_cpu(evt->cpumask);
+
+ switch (mode) {
+ case CLOCK_EVT_MODE_PERIODIC:
+ leon_load_profile_irq(cpu, (1000000 / HZ));
+ break;
+ case CLOCK_EVT_MODE_ONESHOT:
+ case CLOCK_EVT_MODE_SHUTDOWN:
+ case CLOCK_EVT_MODE_UNUSED:
+ leon_load_profile_irq(cpu, 0);
+ break;
+ default:
+ break;
+ }
+}
+
+static int leon_percpu_ce_set_next_event(unsigned long delta,
+ struct clock_event_device *evt)
+{
+ int cpu = __first_cpu(evt->cpumask);
+ unsigned int next = (unsigned int)delta;
+ leon_load_profile_irq(cpu, next);
+ return 0;
+}
+
+void leon_register_percpu_ce(int cpu)
+{
+ struct clock_event_device *ce = &per_cpu(sparc32_clockevent, cpu);
+ unsigned int features = CLOCK_EVT_FEAT_PERIODIC;
+
+ if (sparc_irq_config.features & FEAT_L14_OS)
+ features |= CLOCK_EVT_FEAT_ONESHOT;
+
+ ce->name = "grtimer-ce";
+ ce->rating = 200;
+ ce->features = features;
+ ce->set_mode = leon_percpu_ce_setup;
+ ce->set_next_event = leon_percpu_ce_set_next_event;
+ ce->cpumask = cpumask_of(cpu);
+ ce->shift = 32;
+ ce->mult = div_sc(1000000, NSEC_PER_SEC,
+ ce->shift);
+ ce->max_delta_ns = clockevent_delta2ns(1000000, ce);
+ ce->min_delta_ns = clockevent_delta2ns(100, ce);
+
+ clockevents_register_device(ce);
+}
+
+#endif /* CONFIG_SMP */
+
+void __init leon_init_timers(void)
{
int irq, eirq;
struct device_node *rootnp, *np, *nnp;
@@ -260,6 +438,10 @@ void __init leon_init_timers(irq_handler_t counter_fn)
int ampopts;
int err;
+ late_time_init = leon_late_time_init;
+ get_cycles_offset = leon_cycles_offset;
+ timer_cs_period = 1000000 / HZ;
+
leondebug_irq_disable = 0;
leon_debug_irqout = 0;
master_l10_counter = (unsigned int *)&dummy_master_l10_counter;
@@ -369,7 +551,7 @@ void __init leon_init_timers(irq_handler_t counter_fn)
leon_eirq_setup(eirq);
irq = _leon_build_device_irq(NULL, leon3_gptimer_irq+leon3_gptimer_idx);
- err = request_irq(irq, counter_fn, IRQF_TIMER, "timer", NULL);
+ err = request_irq(irq, leon_timer_interrupt, IRQF_TIMER, "timer", NULL);
if (err) {
printk(KERN_ERR "unable to attach timer IRQ%d\n", irq);
prom_halt();
@@ -401,7 +583,7 @@ void __init leon_init_timers(irq_handler_t counter_fn)
/* Install per-cpu IRQ handler for broadcasted ticker */
irq = leon_build_device_irq(leon3_ticker_irq, handle_percpu_irq,
"per-cpu", 0);
- err = request_irq(irq, leon_percpu_timer_interrupt,
+ err = request_irq(irq, leon_percpu_timer_ce_interrupt,
IRQF_PERCPU | IRQF_TIMER, "ticker",
NULL);
if (err) {
@@ -428,7 +610,6 @@ void leon_clear_clock_irq(void)
void leon_load_profile_irq(int cpu, unsigned int limit)
{
- BUG();
}
void __init leon_trans_init(struct device_node *dp)
diff --git a/arch/sparc/kernel/leon_smp.c b/arch/sparc/kernel/leon_smp.c
index 1210fde..0bda9b1 100644
--- a/arch/sparc/kernel/leon_smp.c
+++ b/arch/sparc/kernel/leon_smp.c
@@ -23,6 +23,8 @@
#include <linux/pm.h>
#include <linux/delay.h>
#include <linux/gfp.h>
+#include <linux/cpu.h>
+#include <linux/clockchips.h>
#include <asm/cacheflush.h>
#include <asm/tlbflush.h>
@@ -42,6 +44,7 @@
#include <asm/asi.h>
#include <asm/leon.h>
#include <asm/leon_amba.h>
+#include <asm/timer.h>
#include "kernel.h"
@@ -68,8 +71,6 @@ static inline unsigned long do_swap(volatile unsigned long *ptr,
return val;
}
-static void smp_setup_percpu_timer(void);
-
void __cpuinit leon_callin(void)
{
int cpuid = hard_smpleon_processor_id();
@@ -79,7 +80,7 @@ void __cpuinit leon_callin(void)
leon_configure_cache_smp();
/* Get our local ticker going. */
- smp_setup_percpu_timer();
+ leon_register_percpu_ce(cpuid);
calibrate_delay();
smp_store_cpu_info(cpuid);
@@ -196,7 +197,6 @@ void __init leon_boot_cpus(void)
leon_smp_setbroadcast(1 << LEON3_IRQ_TICKER);
leon_configure_cache_smp();
- smp_setup_percpu_timer();
local_flush_cache_all();
}
@@ -489,32 +489,6 @@ void leon_cross_call_irq(void)
ccall_info.processors_out[i] = 1;
}
-irqreturn_t leon_percpu_timer_interrupt(int irq, void *unused)
-{
- int cpu = smp_processor_id();
-
- leon_clear_profile_irq(cpu);
-
- profile_tick(CPU_PROFILING);
-
- if (!--prof_counter(cpu)) {
- int user = user_mode(get_irq_regs());
-
- update_process_times(user);
-
- prof_counter(cpu) = prof_multiplier(cpu);
- }
-
- return IRQ_HANDLED;
-}
-
-static void __init smp_setup_percpu_timer(void)
-{
- int cpu = smp_processor_id();
-
- prof_counter(cpu) = prof_multiplier(cpu) = 1;
-}
-
void __init leon_blackbox_id(unsigned *addr)
{
int rd = *addr & 0x3e000000;
diff --git a/arch/sparc/kernel/time_32.c b/arch/sparc/kernel/time_32.c
index fc66bff..7427a49 100644
--- a/arch/sparc/kernel/time_32.c
+++ b/arch/sparc/kernel/time_32.c
@@ -367,12 +367,12 @@ void __init time_init(void)
sparc_irq_config.features = 0;
+ late_time_init = sparc32_late_time_init;
+
if (pcic_present())
pci_time_init();
else
sbus_time_init();
-
- late_time_init = sparc32_late_time_init;
}
--
1.6.1.3
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH 1/1] sparc32,leon: GENERIC_CLOCKEVENTS support for SPARC-LEON
2012-03-15 10:33 [PATCH 1/1] sparc32,leon: GENERIC_CLOCKEVENTS support for SPARC-LEON Konrad Eisele
@ 2012-03-16 22:51 ` Kirill Tkhai
0 siblings, 0 replies; 2+ messages in thread
From: Kirill Tkhai @ 2012-03-16 22:51 UTC (permalink / raw)
To: sparclinux
Thanks a lot, Konrad!
On Thu, 2012-03-15 at 11:33 +0100, Konrad Eisele wrote:
> Add GENERIC_CLOCKEVENTS support for SPARC-LEON.
>
> The late_time_init initialization has been moved to
> enable overriding it for SPARC-LEON.
>
> Signed-off-by: Konrad Eisele <konrad@gaisler.com>
> ---
> arch/sparc/include/asm/leon.h | 3 +-
> arch/sparc/kernel/leon_kernel.c | 189 ++++++++++++++++++++++++++++++++++++++-
> arch/sparc/kernel/leon_smp.c | 34 +------
> arch/sparc/kernel/time_32.c | 4 +-
> 4 files changed, 193 insertions(+), 37 deletions(-)
>
> diff --git a/arch/sparc/include/asm/leon.h b/arch/sparc/include/asm/leon.h
> index a4e457f..9b9b24f 100644
> --- a/arch/sparc/include/asm/leon.h
> +++ b/arch/sparc/include/asm/leon.h
> @@ -323,7 +323,7 @@ extern void leon_update_virq_handling(unsigned int virq,
> const char *name, int do_ack);
> extern void leon_clear_clock_irq(void);
> extern void leon_load_profile_irq(int cpu, unsigned int limit);
> -extern void leon_init_timers(irq_handler_t counter_fn);
> +extern void leon_init_timers(void);
> extern void leon_clear_clock_irq(void);
> extern void leon_load_profile_irq(int cpu, unsigned int limit);
> extern void leon_trans_init(struct device_node *dp);
> @@ -351,6 +351,7 @@ extern void init_IRQ(void);
> extern void cpu_panic(void);
> extern int __leon_processor_id(void);
> void leon_enable_irq_cpu(unsigned int irq_nr, unsigned int cpu);
> +extern void leon_register_percpu_ce(int cpu);
> extern irqreturn_t leon_percpu_timer_interrupt(int irq, void *unused);
>
> extern unsigned int real_irq_entry[];
> diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c
> index a19c8a0..62afe3f 100644
> --- a/arch/sparc/kernel/leon_kernel.c
> +++ b/arch/sparc/kernel/leon_kernel.c
> @@ -10,6 +10,8 @@
> #include <linux/of_platform.h>
> #include <linux/interrupt.h>
> #include <linux/of_device.h>
> +#include <linux/clocksource.h>
> +#include <linux/clockchips.h>
>
> #include <asm/oplib.h>
> #include <asm/timer.h>
> @@ -27,12 +29,18 @@
> struct leon3_irqctrl_regs_map *leon3_irqctrl_regs; /* interrupt controller base address */
> struct leon3_gptimer_regs_map *leon3_gptimer_regs; /* timer controller base address */
>
> +static __cacheline_aligned_in_smp DEFINE_SEQLOCK(leon_timer_cs_lock);
> +static __volatile__ u64 leon_timer_cs_internal_counter = 0;
> int leondebug_irq_disable;
> int leon_debug_irqout;
> static int dummy_master_l10_counter;
> unsigned long amba_system_id;
> static DEFINE_SPINLOCK(leon_irq_lock);
>
> +static char leon_timer_cs_enabled = 0;
> +#ifndef CONFIG_SMP
> +static char leon_timer_ce_enabled = 0;
> +#endif
> unsigned long leon3_gptimer_irq; /* interrupt controller irq number */
> unsigned long leon3_gptimer_idx; /* Timer Index (0..6) within Timer Core */
> int leon3_ticker_irq; /* Timer ticker IRQ */
> @@ -250,7 +258,177 @@ void leon_update_virq_handling(unsigned int virq,
> irq_set_chip_data(virq, (void *)mask);
> }
>
> -void __init leon_init_timers(irq_handler_t counter_fn)
> +static u32 leon_cycles_offset(void)
> +{
> + u32 rld, val, off;
> + rld = LEON3_BYPASS_LOAD_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].rld);
> + val = LEON3_BYPASS_LOAD_PA(&leon3_gptimer_regs->e[leon3_gptimer_idx].val);
> + off = rld - val;
> + return rld - val;
> +}
> +
> +static cycle_t leon_timer_cs_read(struct clocksource *cs)
> +{
> + unsigned int seq, offset;
> + u64 cycles;
> +
> + do {
> + seq = read_seqbegin(&leon_timer_cs_lock);
> + cycles = leon_timer_cs_internal_counter;
> + offset = leon_cycles_offset();
> + } while (read_seqretry(&leon_timer_cs_lock, seq));
> +
> + cycles *= timer_cs_period;
> + cycles += offset;
> + return cycles;
> +}
> +
> +static struct clocksource leon_timer_cs = {
> + .name = "grtimer-cs",
> + .rating = 200,
> + .read = leon_timer_cs_read,
> + .mask = CLOCKSOURCE_MASK(32),
> + .flags = CLOCK_SOURCE_IS_CONTINUOUS,
> +};
> +
> +#ifndef CONFIG_SMP
> +
> +static void leon_timer_ce_set_mode(enum clock_event_mode mode,
> + struct clock_event_device *evt)
> +{
> + switch (mode) {
> + case CLOCK_EVT_MODE_PERIODIC:
> + case CLOCK_EVT_MODE_RESUME:
> + leon_timer_ce_enabled = 1;
> + break;
> + case CLOCK_EVT_MODE_SHUTDOWN:
> + leon_timer_ce_enabled = 0;
> + break;
> + default:
> + break;
> + }
> + smp_mb();
> +}
> +
> +static struct clock_event_device leon_timer_ce = {
> + .name = "grtimer-ce",
> + .rating = 100,
> + .features = CLOCK_EVT_FEAT_PERIODIC,
> + .set_mode = leon_timer_ce_set_mode,
> + .shift = 32
> +};
> +
> +#endif /* !CONFIG_SMP */
> +
> +static void __init leon_late_time_init(void)
> +{
> + leon_timer_cs_enabled = 1;
> +
> + clocksource_register_hz(&leon_timer_cs, 1000000);
> +
> +#ifdef CONFIG_SMP
> + leon_register_percpu_ce(smp_processor_id());
> +#else
> + BUG_ON(smp_processor_id() != boot_cpu_id);
> + leon_timer_ce.cpumask = cpu_possible_mask;
> + leon_timer_ce.mult = div_sc(1000000, NSEC_PER_SEC,
> + leon_timer_ce.shift);
> + clockevents_register_device(&leon_timer_ce);
> +#endif /* CONFIG_SMP */
> +}
> +
> +/* clocksource irq, non-smp clockevent */
> +irqreturn_t notrace leon_timer_interrupt(int dummy, void *dev_id)
> +{
> + if (leon_timer_cs_enabled) {
> + write_seqlock(&leon_timer_cs_lock);
> + leon_timer_cs_internal_counter++;
> + write_sequnlock(&leon_timer_cs_lock);
> + }
> +#ifndef CONFIG_SMP
> + if (leon_timer_ce_enabled) {
> + if (leon_timer_ce.event_handler)
> + leon_timer_ce.event_handler(&leon_timer_ce);
> + }
> +
> +#endif
> + return IRQ_HANDLED;
> +}
> +
> +#ifdef CONFIG_SMP
> +
> +/* smp clockevent irq */
> +irqreturn_t leon_percpu_timer_ce_interrupt(int irq, void *unused)
> +{
> + struct clock_event_device *ce;
> + int cpu = smp_processor_id();
> +
> + leon_clear_profile_irq(cpu);
> +
> + ce = &per_cpu(sparc32_clockevent, cpu);
> +
> + irq_enter();
> + if (ce->event_handler)
> + ce->event_handler(ce);
> + irq_exit();
> +
> + return IRQ_HANDLED;
> +}
> +
> +static void leon_percpu_ce_setup(enum clock_event_mode mode,
> + struct clock_event_device *evt)
> +{
> + int cpu = __first_cpu(evt->cpumask);
> +
> + switch (mode) {
> + case CLOCK_EVT_MODE_PERIODIC:
> + leon_load_profile_irq(cpu, (1000000 / HZ));
> + break;
> + case CLOCK_EVT_MODE_ONESHOT:
> + case CLOCK_EVT_MODE_SHUTDOWN:
> + case CLOCK_EVT_MODE_UNUSED:
> + leon_load_profile_irq(cpu, 0);
> + break;
> + default:
> + break;
> + }
> +}
> +
> +static int leon_percpu_ce_set_next_event(unsigned long delta,
> + struct clock_event_device *evt)
> +{
> + int cpu = __first_cpu(evt->cpumask);
> + unsigned int next = (unsigned int)delta;
> + leon_load_profile_irq(cpu, next);
> + return 0;
> +}
> +
> +void leon_register_percpu_ce(int cpu)
> +{
> + struct clock_event_device *ce = &per_cpu(sparc32_clockevent, cpu);
> + unsigned int features = CLOCK_EVT_FEAT_PERIODIC;
> +
> + if (sparc_irq_config.features & FEAT_L14_OS)
> + features |= CLOCK_EVT_FEAT_ONESHOT;
> +
> + ce->name = "grtimer-ce";
> + ce->rating = 200;
> + ce->features = features;
> + ce->set_mode = leon_percpu_ce_setup;
> + ce->set_next_event = leon_percpu_ce_set_next_event;
> + ce->cpumask = cpumask_of(cpu);
> + ce->shift = 32;
> + ce->mult = div_sc(1000000, NSEC_PER_SEC,
> + ce->shift);
> + ce->max_delta_ns = clockevent_delta2ns(1000000, ce);
> + ce->min_delta_ns = clockevent_delta2ns(100, ce);
> +
> + clockevents_register_device(ce);
> +}
> +
> +#endif /* CONFIG_SMP */
> +
> +void __init leon_init_timers(void)
> {
> int irq, eirq;
> struct device_node *rootnp, *np, *nnp;
> @@ -260,6 +438,10 @@ void __init leon_init_timers(irq_handler_t counter_fn)
> int ampopts;
> int err;
>
> + late_time_init = leon_late_time_init;
> + get_cycles_offset = leon_cycles_offset;
> + timer_cs_period = 1000000 / HZ;
> +
> leondebug_irq_disable = 0;
> leon_debug_irqout = 0;
> master_l10_counter = (unsigned int *)&dummy_master_l10_counter;
> @@ -369,7 +551,7 @@ void __init leon_init_timers(irq_handler_t counter_fn)
> leon_eirq_setup(eirq);
>
> irq = _leon_build_device_irq(NULL, leon3_gptimer_irq+leon3_gptimer_idx);
> - err = request_irq(irq, counter_fn, IRQF_TIMER, "timer", NULL);
> + err = request_irq(irq, leon_timer_interrupt, IRQF_TIMER, "timer", NULL);
> if (err) {
> printk(KERN_ERR "unable to attach timer IRQ%d\n", irq);
> prom_halt();
> @@ -401,7 +583,7 @@ void __init leon_init_timers(irq_handler_t counter_fn)
> /* Install per-cpu IRQ handler for broadcasted ticker */
> irq = leon_build_device_irq(leon3_ticker_irq, handle_percpu_irq,
> "per-cpu", 0);
> - err = request_irq(irq, leon_percpu_timer_interrupt,
> + err = request_irq(irq, leon_percpu_timer_ce_interrupt,
> IRQF_PERCPU | IRQF_TIMER, "ticker",
> NULL);
> if (err) {
> @@ -428,7 +610,6 @@ void leon_clear_clock_irq(void)
>
> void leon_load_profile_irq(int cpu, unsigned int limit)
> {
> - BUG();
> }
>
> void __init leon_trans_init(struct device_node *dp)
> diff --git a/arch/sparc/kernel/leon_smp.c b/arch/sparc/kernel/leon_smp.c
> index 1210fde..0bda9b1 100644
> --- a/arch/sparc/kernel/leon_smp.c
> +++ b/arch/sparc/kernel/leon_smp.c
> @@ -23,6 +23,8 @@
> #include <linux/pm.h>
> #include <linux/delay.h>
> #include <linux/gfp.h>
> +#include <linux/cpu.h>
> +#include <linux/clockchips.h>
>
> #include <asm/cacheflush.h>
> #include <asm/tlbflush.h>
> @@ -42,6 +44,7 @@
> #include <asm/asi.h>
> #include <asm/leon.h>
> #include <asm/leon_amba.h>
> +#include <asm/timer.h>
>
> #include "kernel.h"
>
> @@ -68,8 +71,6 @@ static inline unsigned long do_swap(volatile unsigned long *ptr,
> return val;
> }
>
> -static void smp_setup_percpu_timer(void);
> -
> void __cpuinit leon_callin(void)
> {
> int cpuid = hard_smpleon_processor_id();
> @@ -79,7 +80,7 @@ void __cpuinit leon_callin(void)
> leon_configure_cache_smp();
>
> /* Get our local ticker going. */
> - smp_setup_percpu_timer();
> + leon_register_percpu_ce(cpuid);
>
> calibrate_delay();
> smp_store_cpu_info(cpuid);
> @@ -196,7 +197,6 @@ void __init leon_boot_cpus(void)
> leon_smp_setbroadcast(1 << LEON3_IRQ_TICKER);
>
> leon_configure_cache_smp();
> - smp_setup_percpu_timer();
> local_flush_cache_all();
>
> }
> @@ -489,32 +489,6 @@ void leon_cross_call_irq(void)
> ccall_info.processors_out[i] = 1;
> }
>
> -irqreturn_t leon_percpu_timer_interrupt(int irq, void *unused)
> -{
> - int cpu = smp_processor_id();
> -
> - leon_clear_profile_irq(cpu);
> -
> - profile_tick(CPU_PROFILING);
> -
> - if (!--prof_counter(cpu)) {
> - int user = user_mode(get_irq_regs());
> -
> - update_process_times(user);
> -
> - prof_counter(cpu) = prof_multiplier(cpu);
> - }
> -
> - return IRQ_HANDLED;
> -}
> -
> -static void __init smp_setup_percpu_timer(void)
> -{
> - int cpu = smp_processor_id();
> -
> - prof_counter(cpu) = prof_multiplier(cpu) = 1;
> -}
> -
> void __init leon_blackbox_id(unsigned *addr)
> {
> int rd = *addr & 0x3e000000;
> diff --git a/arch/sparc/kernel/time_32.c b/arch/sparc/kernel/time_32.c
> index fc66bff..7427a49 100644
> --- a/arch/sparc/kernel/time_32.c
> +++ b/arch/sparc/kernel/time_32.c
> @@ -367,12 +367,12 @@ void __init time_init(void)
>
> sparc_irq_config.features = 0;
>
> + late_time_init = sparc32_late_time_init;
> +
> if (pcic_present())
> pci_time_init();
> else
> sbus_time_init();
> -
> - late_time_init = sparc32_late_time_init;
> }
>
>
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2012-03-16 22:51 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-03-15 10:33 [PATCH 1/1] sparc32,leon: GENERIC_CLOCKEVENTS support for SPARC-LEON Konrad Eisele
2012-03-16 22:51 ` Kirill Tkhai
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.