diff options
Diffstat (limited to 'drivers/clocksource/exynos_mct.c')
| -rw-r--r-- | drivers/clocksource/exynos_mct.c | 51 |
1 files changed, 38 insertions, 13 deletions
diff --git a/drivers/clocksource/exynos_mct.c b/drivers/clocksource/exynos_mct.c index 5b34768f4d7..ab51bf20a3e 100644 --- a/drivers/clocksource/exynos_mct.c +++ b/drivers/clocksource/exynos_mct.c @@ -24,8 +24,7 @@ #include <linux/of_irq.h> #include <linux/of_address.h> #include <linux/clocksource.h> - -#include <asm/mach/time.h> +#include <linux/sched_clock.h> #define EXYNOS4_MCTREG(x) (x) #define EXYNOS4_MCT_G_CNT_L EXYNOS4_MCTREG(0x100) @@ -71,6 +70,10 @@ enum { MCT_L1_IRQ, MCT_L2_IRQ, MCT_L3_IRQ, + MCT_L4_IRQ, + MCT_L5_IRQ, + MCT_L6_IRQ, + MCT_L7_IRQ, MCT_NR_IRQS, }; @@ -150,19 +153,16 @@ static void exynos4_mct_write(unsigned int value, unsigned long offset) } /* Clocksource handling */ -static void exynos4_mct_frc_start(u32 hi, u32 lo) +static void exynos4_mct_frc_start(void) { u32 reg; - exynos4_mct_write(lo, EXYNOS4_MCT_G_CNT_L); - exynos4_mct_write(hi, EXYNOS4_MCT_G_CNT_U); - reg = __raw_readl(reg_base + EXYNOS4_MCT_G_TCON); reg |= MCT_G_TCON_START; exynos4_mct_write(reg, EXYNOS4_MCT_G_TCON); } -static cycle_t exynos4_frc_read(struct clocksource *cs) +static cycle_t notrace _exynos4_frc_read(void) { unsigned int lo, hi; u32 hi2 = __raw_readl(reg_base + EXYNOS4_MCT_G_CNT_U); @@ -176,9 +176,14 @@ static cycle_t exynos4_frc_read(struct clocksource *cs) return ((cycle_t)hi << 32) | lo; } +static cycle_t exynos4_frc_read(struct clocksource *cs) +{ + return _exynos4_frc_read(); +} + static void exynos4_frc_resume(struct clocksource *cs) { - exynos4_mct_frc_start(0, 0); + exynos4_mct_frc_start(); } struct clocksource mct_frc = { @@ -190,12 +195,30 @@ struct clocksource mct_frc = { .resume = exynos4_frc_resume, }; +static u64 notrace exynos4_read_sched_clock(void) +{ + return _exynos4_frc_read(); +} + +static struct delay_timer exynos4_delay_timer; + +static cycles_t exynos4_read_current_timer(void) +{ + return _exynos4_frc_read(); +} + static void __init exynos4_clocksource_init(void) { - exynos4_mct_frc_start(0, 0); + exynos4_mct_frc_start(); + + exynos4_delay_timer.read_current_timer = &exynos4_read_current_timer; + exynos4_delay_timer.freq = clk_rate; + register_current_timer_delay(&exynos4_delay_timer); if (clocksource_register_hz(&mct_frc, clk_rate)) panic("%s: can't register clocksource\n", mct_frc.name); + + sched_clock_register(exynos4_read_sched_clock, 64, clk_rate); } static void exynos4_mct_comp0_stop(void) @@ -406,7 +429,7 @@ static int exynos4_local_timer_setup(struct clock_event_device *evt) mevt = container_of(evt, struct mct_clock_event_device, evt); mevt->base = EXYNOS4_MCT_L_BASE(cpu); - sprintf(mevt->name, "mct_tick%d", cpu); + snprintf(mevt->name, sizeof(mevt->name), "mct_tick%d", cpu); evt->name = mevt->name; evt->cpumask = cpumask_of(cpu); @@ -414,8 +437,6 @@ static int exynos4_local_timer_setup(struct clock_event_device *evt) evt->set_mode = exynos4_tick_set_mode; evt->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; evt->rating = 450; - clockevents_config_and_register(evt, clk_rate / (TICK_BASE_CNT + 1), - 0xf, 0x7fffffff); exynos4_mct_write(TICK_BASE_CNT, mevt->base + MCT_L_TCNTB_OFFSET); @@ -428,10 +449,12 @@ static int exynos4_local_timer_setup(struct clock_event_device *evt) evt->irq); return -EIO; } - irq_set_affinity(evt->irq, cpumask_of(cpu)); + irq_force_affinity(mct_irqs[MCT_L0_IRQ + cpu], cpumask_of(cpu)); } else { enable_percpu_irq(mct_irqs[MCT_L0_IRQ], 0); } + clockevents_config_and_register(evt, clk_rate / (TICK_BASE_CNT + 1), + 0xf, 0x7fffffff); return 0; } @@ -500,6 +523,8 @@ static void __init exynos4_timer_resources(struct device_node *np, void __iomem &percpu_mct_tick); WARN(err, "MCT: can't request IRQ %d (%d)\n", mct_irqs[MCT_L0_IRQ], err); + } else { + irq_set_affinity(mct_irqs[MCT_L0_IRQ], cpumask_of(0)); } err = register_cpu_notifier(&exynos4_mct_cpu_nb); |
