/* * time.c: Baget/MIPS specific time handling details * * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* * To have precision clock, we need to fix available clock frequency */ #define FREQ_NOM 79125 /* Baget frequency ratio */ #define FREQ_DEN 10000 static inline int timer_intr_valid(void) { static unsigned long long ticks, valid_ticks; if (ticks++ * FREQ_DEN >= valid_ticks * FREQ_NOM) { /* * We need no overflow checks, * due baget unable to work 3000 years... * At least without reboot... */ valid_ticks++; return 1; } return 0; } void static timer_interrupt(int irq, void *dev_id, struct pt_regs * regs) { if (timer_intr_valid()) { sti(); do_timer(regs); } } static void __init timer_enable(void) { unsigned char ss0cr0 = vic_inb(VIC_SS0CR0); ss0cr0 &= ~VIC_SS0CR0_TIMER_FREQ_MASK; ss0cr0 |= VIC_SS0CR0_TIMER_FREQ_1000HZ; vic_outb(ss0cr0, VIC_SS0CR0); vic_outb(VIC_INT_IPL(6)|VIC_INT_NOAUTO|VIC_INT_EDGE| VIC_INT_LOW|VIC_INT_ENABLE, VIC_LINT2); } static struct irqaction timer_irq = { timer_interrupt, SA_INTERRUPT, 0, "timer", NULL, NULL}; void __init time_init(void) { if (setup_baget_irq(BAGET_VIC_TIMER_IRQ, &timer_irq) < 0) printk("time_init: unable request irq for system timer\n"); timer_enable(); /* We don't call sti() here, because it is too early for baget */ } void do_gettimeofday(struct timeval *tv) { unsigned long seq; do { seq = read_seqbegin(&xtime_lock); tv->tv_sec = xtime.tv_sec; tv->tv_usec = xtime.tv_nsec / 1000; } while (read_seqretry(&xtime_lock, seq)); } EXPORT_SYMBOL(do_gettimeofday); void do_settimeofday(struct timeval *tv) { write_seqlock_irq(&xtime_lock); xtime.tv_usec = tv->tv_sec; xtime.tv_nsec = tv->tv_usec; time_adjust = 0; /* stop active adjtime() */ time_status |= STA_UNSYNC; time_maxerror = NTP_PHASE_LIMIT; time_esterror = NTP_PHASE_LIMIT; write_sequnlock_irq(&xtime_lock); } EXPORT_SYMBOL(do_settimeofday);