]> err.no Git - linux-2.6/blobdiff - arch/mips/philips/pnx8550/common/time.c
Merge branch 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus
[linux-2.6] / arch / mips / philips / pnx8550 / common / time.c
index f80acae07ceecebb0927ca759f918ea484dc1d5a..6d494e0de3d97cb60beea553a515d8a9c65281ec 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright 2001, 2002, 2003 MontaVista Software Inc.
  * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ * Copyright (C) 2007 Ralf Baechle (ralf@linux-mips.org)
  *
  * Common time service routines for MIPS machines. See
  * Documents/MIPS/README.txt.
@@ -21,7 +22,6 @@
 #include <linux/kernel_stat.h>
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
-#include <linux/module.h>
 
 #include <asm/bootinfo.h>
 #include <asm/cpu.h>
@@ -40,28 +40,100 @@ static cycle_t hpt_read(void)
        return read_c0_count2();
 }
 
+static struct clocksource pnx_clocksource = {
+       .name           = "pnx8xxx",
+       .rating         = 200,
+       .read           = hpt_read,
+       .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
 static void timer_ack(void)
 {
        write_c0_compare(cpj);
 }
 
+static irqreturn_t pnx8xxx_timer_interrupt(int irq, void *dev_id)
+{
+       struct clock_event_device *c = dev_id;
+
+       /* clear MATCH, signal the event */
+       c->event_handler(c);
+
+       return IRQ_HANDLED;
+}
+
+static struct irqaction pnx8xxx_timer_irq = {
+       .handler        = pnx8xxx_timer_interrupt,
+       .flags          = IRQF_DISABLED | IRQF_PERCPU,
+       .name           = "pnx8xxx_timer",
+};
+
+static irqreturn_t monotonic_interrupt(int irq, void *dev_id)
+{
+       /* Timer 2 clear interrupt */
+       write_c0_compare2(-1);
+       return IRQ_HANDLED;
+}
+
+static struct irqaction monotonic_irqaction = {
+       .handler = monotonic_interrupt,
+       .flags = IRQF_DISABLED,
+       .name = "Monotonic timer",
+};
+
+static int pnx8xxx_set_next_event(unsigned long delta,
+                               struct clock_event_device *evt)
+{
+       write_c0_compare(delta);
+       return 0;
+}
+
+static struct clock_event_device pnx8xxx_clockevent = {
+       .name           = "pnx8xxx_clockevent",
+       .features       = CLOCK_EVT_FEAT_ONESHOT,
+       .set_next_event = pnx8xxx_set_next_event,
+};
+
 /*
- * pnx8550_time_init() - it does the following things:
+ * plat_time_init() - it does the following things:
  *
- * 1) board_time_init() -
+ * 1) plat_time_init() -
  *     a) (optional) set up RTC routines,
  *      b) (optional) calibrate and set the mips_hpt_frequency
  *         (only needed if you intended to use cpu counter as timer interrupt
  *          source)
  */
 
-void pnx8550_time_init(void)
+__init void plat_time_init(void)
 {
+       unsigned int             configPR;
        unsigned int             n;
        unsigned int             m;
        unsigned int             p;
        unsigned int             pow2p;
 
+       clockevents_register_device(&pnx8xxx_clockevent);
+       clocksource_register(&pnx_clocksource);
+
+       setup_irq(PNX8550_INT_TIMER1, &pnx8xxx_timer_irq);
+       setup_irq(PNX8550_INT_TIMER2, &monotonic_irqaction);
+
+       /* Timer 1 start */
+       configPR = read_c0_config7();
+       configPR &= ~0x00000008;
+       write_c0_config7(configPR);
+
+       /* Timer 2 start */
+       configPR = read_c0_config7();
+       configPR &= ~0x00000010;
+       write_c0_config7(configPR);
+
+       /* Timer 3 stop */
+       configPR = read_c0_config7();
+       configPR |= 0x00000020;
+       write_c0_config7(configPR);
+
+
         /* PLL0 sets MIPS clock (PLL1 <=> TM1, PLL6 <=> TM2, PLL5 <=> mem) */
         /* (but only if CLK_MIPS_CTL select value [bits 3:1] is 1:  FIXME) */
 
@@ -79,48 +151,13 @@ void pnx8550_time_init(void)
         */
        mips_hpt_frequency = 27UL * ((1000000UL * n)/(m * pow2p));
        cpj = (mips_hpt_frequency + HZ / 2) / HZ;
+       write_c0_count(0);
        timer_ack();
 
        /* Setup Timer 2 */
        write_c0_count2(0);
        write_c0_compare2(0xffffffff);
 
-       clocksource_mips.read = hpt_read;
-       mips_timer_ack = timer_ack;
-}
-
-static irqreturn_t monotonic_interrupt(int irq, void *dev_id)
-{
-       /* Timer 2 clear interrupt */
-       write_c0_compare2(-1);
-       return IRQ_HANDLED;
 }
 
-static struct irqaction monotonic_irqaction = {
-       .handler = monotonic_interrupt,
-       .flags = IRQF_DISABLED,
-       .name = "Monotonic timer",
-};
 
-void __init plat_timer_setup(struct irqaction *irq)
-{
-       int configPR;
-
-       setup_irq(PNX8550_INT_TIMER1, irq);
-       setup_irq(PNX8550_INT_TIMER2, &monotonic_irqaction);
-
-       /* Timer 1 start */
-       configPR = read_c0_config7();
-       configPR &= ~0x00000008;
-       write_c0_config7(configPR);
-
-       /* Timer 2 start */
-       configPR = read_c0_config7();
-       configPR &= ~0x00000010;
-       write_c0_config7(configPR);
-
-       /* Timer 3 stop */
-       configPR = read_c0_config7();
-       configPR |= 0x00000020;
-       write_c0_config7(configPR);
-}