diff options
Diffstat (limited to 'arch/mips/philips/pnx8550/common/time.c')
-rw-r--r-- | arch/mips/philips/pnx8550/common/time.c | 120 |
1 files changed, 71 insertions, 49 deletions
diff --git a/arch/mips/philips/pnx8550/common/time.c b/arch/mips/philips/pnx8550/common/time.c index e818fd0f1584..62f495b57f93 100644 --- a/arch/mips/philips/pnx8550/common/time.c +++ b/arch/mips/philips/pnx8550/common/time.c @@ -22,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> @@ -41,56 +40,29 @@ static cycle_t hpt_read(void) return read_c0_count2(); } -static void timer_ack(void) -{ - write_c0_compare(cpj); -} - -/* - * plat_time_init() - it does the following things: - * - * 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) - */ +static struct clocksource pnx_clocksource = { + .name = "pnx8xxx", + .rating = 200, + .read = hpt_read, + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; -__init void plat_time_init(void) +static irqreturn_t pnx8xxx_timer_interrupt(int irq, void *dev_id) { - unsigned int n; - unsigned int m; - unsigned int p; - unsigned int pow2p; + struct clock_event_device *c = dev_id; - /* PLL0 sets MIPS clock (PLL1 <=> TM1, PLL6 <=> TM2, PLL5 <=> mem) */ - /* (but only if CLK_MIPS_CTL select value [bits 3:1] is 1: FIXME) */ + /* clear MATCH, signal the event */ + c->event_handler(c); - n = (PNX8550_CM_PLL0_CTL & PNX8550_CM_PLL_N_MASK) >> 16; - m = (PNX8550_CM_PLL0_CTL & PNX8550_CM_PLL_M_MASK) >> 8; - p = (PNX8550_CM_PLL0_CTL & PNX8550_CM_PLL_P_MASK) >> 2; - pow2p = (1 << p); - - db_assert(m != 0 && pow2p != 0); - - /* - * Compute the frequency as in the PNX8550 User Manual 1.0, p.186 - * (a.k.a. 8-10). Divide by HZ for a timer offset that results in - * HZ timer interrupts per second. - */ - 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; + 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 */ @@ -104,12 +76,34 @@ static struct irqaction monotonic_irqaction = { .name = "Monotonic timer", }; -void __init plat_timer_setup(struct irqaction *irq) +static int pnx8xxx_set_next_event(unsigned long delta, + struct clock_event_device *evt) { - int configPR; + write_c0_compare(delta); + return 0; +} - setup_irq(PNX8550_INT_TIMER1, irq); - setup_irq(PNX8550_INT_TIMER2, &monotonic_irqaction); +static struct clock_event_device pnx8xxx_clockevent = { + .name = "pnx8xxx_clockevent", + .features = CLOCK_EVT_FEAT_ONESHOT, + .set_next_event = pnx8xxx_set_next_event, +}; + +static inline void timer_ack(void) +{ + write_c0_compare(cpj); +} + +__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); /* Timer 1 start */ configPR = read_c0_config7(); @@ -125,4 +119,32 @@ void __init plat_timer_setup(struct irqaction *irq) 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) */ + + n = (PNX8550_CM_PLL0_CTL & PNX8550_CM_PLL_N_MASK) >> 16; + m = (PNX8550_CM_PLL0_CTL & PNX8550_CM_PLL_M_MASK) >> 8; + p = (PNX8550_CM_PLL0_CTL & PNX8550_CM_PLL_P_MASK) >> 2; + pow2p = (1 << p); + + db_assert(m != 0 && pow2p != 0); + + /* + * Compute the frequency as in the PNX8550 User Manual 1.0, p.186 + * (a.k.a. 8-10). Divide by HZ for a timer offset that results in + * HZ timer interrupts per second. + */ + 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); + + setup_irq(PNX8550_INT_TIMER1, &pnx8xxx_timer_irq); + setup_irq(PNX8550_INT_TIMER2, &monotonic_irqaction); } |