diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-05-06 16:39:31 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-05-06 16:39:31 -0700 |
commit | ccbc2e5ed192ccd2663477107379f843d072e649 (patch) | |
tree | 13a180031283a7cc2275902cf45e1bc1d9cd5ee6 /arch/m68k/mvme147 | |
parent | Merge branch 'x86-microcode-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip (diff) | |
parent | Documentation/features/time: Mark m68k having modern-timekeeping (diff) | |
download | linux-dev-ccbc2e5ed192ccd2663477107379f843d072e649.tar.xz linux-dev-ccbc2e5ed192ccd2663477107379f843d072e649.zip |
Merge tag 'm68k-for-v5.2-tag1' of git://git.kernel.org/pub/scm/linux/kernel/git/geert/linux-m68k
Pull m68k updates from Geert Uytterhoeven:
- drop arch_gettimeoffset and adopt clocksource API
- defconfig updates
* tag 'm68k-for-v5.2-tag1' of git://git.kernel.org/pub/scm/linux/kernel/git/geert/linux-m68k:
Documentation/features/time: Mark m68k having modern-timekeeping
m68k: defconfig: Update defconfigs for v5.1-rc1
m68k: mvme16x: Handle timer counter overflow
m68k: mvme16x: Convert to clocksource API
m68k: mvme147: Handle timer counter overflow
m68k: mvme147: Convert to clocksource API
m68k: mac: Convert to clocksource API
m68k: hp300: Handle timer counter overflow
m68k: hp300: Convert to clocksource API
m68k: bvme6000: Convert to clocksource API
m68k: atari: Convert to clocksource API
m68k: amiga: Convert to clocksource API
m68k: Drop ARCH_USES_GETTIMEOFFSET
m68k: apollo, q40, sun3, sun3x: Remove arch_gettimeoffset implementations
m68k: mac: Fix VIA timer counter accesses
m68k: Call timer_interrupt() with interrupts disabled
Diffstat (limited to 'arch/m68k/mvme147')
-rw-r--r-- | arch/m68k/mvme147/config.c | 73 |
1 files changed, 49 insertions, 24 deletions
diff --git a/arch/m68k/mvme147/config.c b/arch/m68k/mvme147/config.c index adea549d240e..545a1fe0e119 100644 --- a/arch/m68k/mvme147/config.c +++ b/arch/m68k/mvme147/config.c @@ -17,6 +17,7 @@ #include <linux/kernel.h> #include <linux/mm.h> #include <linux/tty.h> +#include <linux/clocksource.h> #include <linux/console.h> #include <linux/linkage.h> #include <linux/init.h> @@ -38,18 +39,12 @@ static void mvme147_get_model(char *model); extern void mvme147_sched_init(irq_handler_t handler); -extern u32 mvme147_gettimeoffset(void); extern int mvme147_hwclk (int, struct rtc_time *); extern void mvme147_reset (void); static int bcd2int (unsigned char b); -/* Save tick handler routine pointer, will point to xtime_update() in - * kernel/time/timekeeping.c, called via mvme147_process_int() */ - -irq_handler_t tick_handler; - int __init mvme147_parse_bootinfo(const struct bi_record *bi) { @@ -89,7 +84,6 @@ void __init config_mvme147(void) mach_max_dma_address = 0x01000000; mach_sched_init = mvme147_sched_init; mach_init_IRQ = mvme147_init_IRQ; - arch_gettimeoffset = mvme147_gettimeoffset; mach_hwclk = mvme147_hwclk; mach_reset = mvme147_reset; mach_get_model = mvme147_get_model; @@ -99,45 +93,76 @@ void __init config_mvme147(void) vme_brdtype = VME_TYPE_MVME147; } +static u64 mvme147_read_clk(struct clocksource *cs); + +static struct clocksource mvme147_clk = { + .name = "pcc", + .rating = 250, + .read = mvme147_read_clk, + .mask = CLOCKSOURCE_MASK(32), + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +static u32 clk_total; + +#define PCC_TIMER_CLOCK_FREQ 160000 +#define PCC_TIMER_CYCLES (PCC_TIMER_CLOCK_FREQ / HZ) +#define PCC_TIMER_PRELOAD (0x10000 - PCC_TIMER_CYCLES) /* Using pcc tick timer 1 */ static irqreturn_t mvme147_timer_int (int irq, void *dev_id) { + irq_handler_t timer_routine = dev_id; + unsigned long flags; + + local_irq_save(flags); m147_pcc->t1_int_cntrl = PCC_TIMER_INT_CLR; - m147_pcc->t1_int_cntrl = PCC_INT_ENAB|PCC_LEVEL_TIMER1; - return tick_handler(irq, dev_id); + m147_pcc->t1_cntrl = PCC_TIMER_CLR_OVF; + clk_total += PCC_TIMER_CYCLES; + timer_routine(0, NULL); + local_irq_restore(flags); + + return IRQ_HANDLED; } void mvme147_sched_init (irq_handler_t timer_routine) { - tick_handler = timer_routine; - if (request_irq(PCC_IRQ_TIMER1, mvme147_timer_int, 0, "timer 1", NULL)) + if (request_irq(PCC_IRQ_TIMER1, mvme147_timer_int, IRQF_TIMER, + "timer 1", timer_routine)) pr_err("Couldn't register timer interrupt\n"); /* Init the clock with a value */ - /* our clock goes off every 6.25us */ + /* The clock counter increments until 0xFFFF then reloads */ m147_pcc->t1_preload = PCC_TIMER_PRELOAD; m147_pcc->t1_cntrl = 0x0; /* clear timer */ m147_pcc->t1_cntrl = 0x3; /* start timer */ m147_pcc->t1_int_cntrl = PCC_TIMER_INT_CLR; /* clear pending ints */ m147_pcc->t1_int_cntrl = PCC_INT_ENAB|PCC_LEVEL_TIMER1; + + clocksource_register_hz(&mvme147_clk, PCC_TIMER_CLOCK_FREQ); } -/* This is always executed with interrupts disabled. */ -/* XXX There are race hazards in this code XXX */ -u32 mvme147_gettimeoffset(void) +static u64 mvme147_read_clk(struct clocksource *cs) { - volatile unsigned short *cp = (volatile unsigned short *)0xfffe1012; - unsigned short n; - - n = *cp; - while (n != *cp) - n = *cp; - - n -= PCC_TIMER_PRELOAD; - return ((unsigned long)n * 25 / 4) * 1000; + unsigned long flags; + u8 overflow, tmp; + u16 count; + u32 ticks; + + local_irq_save(flags); + tmp = m147_pcc->t1_cntrl >> 4; + count = m147_pcc->t1_count; + overflow = m147_pcc->t1_cntrl >> 4; + if (overflow != tmp) + count = m147_pcc->t1_count; + count -= PCC_TIMER_PRELOAD; + ticks = count + overflow * PCC_TIMER_CYCLES; + ticks += clk_total; + local_irq_restore(flags); + + return ticks; } static int bcd2int (unsigned char b) |