Commit 3384df06 authored by Finn Thain's avatar Finn Thain Committed by Geert Uytterhoeven
Browse files

m68k: bvme6000: Convert to clocksource API



Add a platform clocksource by adapting the existing arch_gettimeoffset
implementation.

Signed-off-by: default avatarFinn Thain <fthain@telegraphics.com.au>
Acked-by: default avatarLinus Walleij <linus.walleij@linaro.org>
Signed-off-by: default avatarGeert Uytterhoeven <geert@linux-m68k.org>
parent 26ccd2d3
Loading
Loading
Loading
Loading
+41 −16
Original line number Diff line number Diff line
@@ -18,6 +18,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>
@@ -147,6 +148,21 @@ irqreturn_t bvme6000_abort_int (int irq, void *dev_id)
	return IRQ_HANDLED;
}

static u64 bvme6000_read_clk(struct clocksource *cs);

static struct clocksource bvme6000_clk = {
	.name   = "rtc",
	.rating = 250,
	.read   = bvme6000_read_clk,
	.mask   = CLOCKSOURCE_MASK(32),
	.flags  = CLOCK_SOURCE_IS_CONTINUOUS,
};

static u32 clk_total, clk_offset;

#define RTC_TIMER_CLOCK_FREQ 8000000
#define RTC_TIMER_CYCLES     (RTC_TIMER_CLOCK_FREQ / HZ)
#define RTC_TIMER_COUNT      ((RTC_TIMER_CYCLES / 2) - 1)

static irqreturn_t bvme6000_timer_int (int irq, void *dev_id)
{
@@ -158,6 +174,8 @@ static irqreturn_t bvme6000_timer_int (int irq, void *dev_id)
    local_irq_save(flags);
    msr = rtc->msr & 0xc0;
    rtc->msr = msr | 0x20;		/* Ack the interrupt */
    clk_total += RTC_TIMER_CYCLES;
    clk_offset = 0;
    timer_routine(0, NULL);
    local_irq_restore(flags);

@@ -180,13 +198,13 @@ void bvme6000_sched_init (irq_handler_t timer_routine)

    rtc->msr = 0;	/* Ensure timer registers accessible */

    if (request_irq(BVME_IRQ_RTC, bvme6000_timer_int, 0, "timer",
    if (request_irq(BVME_IRQ_RTC, bvme6000_timer_int, IRQF_TIMER, "timer",
                    timer_routine))
	panic ("Couldn't register timer int");

    rtc->t1cr_omr = 0x04;	/* Mode 2, ext clk */
    rtc->t1msb = 39999 >> 8;
    rtc->t1lsb = 39999 & 0xff;
    rtc->t1msb = RTC_TIMER_COUNT >> 8;
    rtc->t1lsb = RTC_TIMER_COUNT & 0xff;
    rtc->irr_icr1 &= 0xef;	/* Route timer 1 to INTR pin */
    rtc->msr = 0x40;		/* Access int.cntrl, etc */
    rtc->pfr_icr0 = 0x80;	/* Just timer 1 ints enabled */
@@ -198,14 +216,14 @@ void bvme6000_sched_init (irq_handler_t timer_routine)

    rtc->msr = msr;

    clocksource_register_hz(&bvme6000_clk, RTC_TIMER_CLOCK_FREQ);

    if (request_irq(BVME_IRQ_ABORT, bvme6000_abort_int, 0,
				"abort", bvme6000_abort_int))
	panic ("Couldn't register abort int");
}


/* This is always executed with interrupts disabled.  */

/*
 * NOTE:  Don't accept any readings within 5us of rollover, as
 * the T1INT bit may be a little slow getting set.  There is also
@@ -213,14 +231,18 @@ void bvme6000_sched_init (irq_handler_t timer_routine)
 * results...
 */

u32 bvme6000_gettimeoffset(void)
static u64 bvme6000_read_clk(struct clocksource *cs)
{
    unsigned long flags;
    volatile RtcPtr_t rtc = (RtcPtr_t)BVME_RTC_BASE;
    volatile PitRegsPtr pit = (PitRegsPtr)BVME_PIT_BASE;
    unsigned char msr = rtc->msr & 0xc0;
    unsigned char msr, msb;
    unsigned char t1int, t1op;
    u32 v = 800000, ov;

    local_irq_save(flags);

    msr = rtc->msr & 0xc0;
    rtc->msr = 0;	/* Ensure timer registers accessible */

    do {
@@ -228,22 +250,25 @@ u32 bvme6000_gettimeoffset(void)
	t1int = rtc->msr & 0x20;
	t1op  = pit->pcdr & 0x04;
	rtc->t1cr_omr |= 0x40;		/* Latch timer1 */
	v = rtc->t1msb << 8;		/* Read timer1 */
	v |= rtc->t1lsb;		/* Read timer1 */
	msb = rtc->t1msb;		/* Read timer1 */
	v = (msb << 8) | rtc->t1lsb;	/* Read timer1 */
    } while (t1int != (rtc->msr & 0x20) ||
		t1op != (pit->pcdr & 0x04) ||
			abs(ov-v) > 80 ||
				v > 39960);
				v > RTC_TIMER_COUNT - (RTC_TIMER_COUNT / 100));

    v = 39999 - v;
    v = RTC_TIMER_COUNT - v;
    if (!t1op)				/* If in second half cycle.. */
	v += 40000;
    v /= 8;				/* Convert ticks to microseconds */
    if (t1int)
	v += 10000;			/* Int pending, + 10ms */
	v += RTC_TIMER_CYCLES / 2;
    if (msb > 0 && t1int)
	clk_offset = RTC_TIMER_CYCLES;
    rtc->msr = msr;

    return v * 1000;
    v += clk_offset + clk_total;

    local_irq_restore(flags);

    return v;
}

/*