diff -Nru linux/arch/mips/au1000/common/time.c.orig linux/arch/mips/au1000/common/time.c --- linux/arch/mips/au1000/common/time.c.orig 2003-10-24 15:07:10.000000000 -0700 +++ linux/arch/mips/au1000/common/time.c 2004-02-11 18:09:49.000000000 -0800 @@ -53,74 +53,25 @@ #error "Alchemy processors need CONFIG_NEW_TIME_C defined" #endif +#if defined(CONFIG_PM) && defined(CONFIG_HIGH_RES_TIMERS) +#error "Power management is not compatible with high resolution timers" +#endif + extern void startup_match20_interrupt(void); extern void do_softirq(void); extern volatile unsigned long wall_jiffies; unsigned long missed_heart_beats = 0; -static unsigned long r4k_offset; /* Amount to increment compare reg each time */ -static unsigned long r4k_cur; /* What counter should be at next timer irq */ extern rwlock_t xtime_lock; int no_au1xxx_32khz; void (*au1k_wait_ptr)(void); -/* Cycle counter value at the previous timer interrupt.. */ -static unsigned int timerhi = 0, timerlo = 0; - #ifdef CONFIG_PM #define MATCH20_INC 328 extern void startup_match20_interrupt(void); static unsigned long last_pc0, last_match20; #endif -static spinlock_t time_lock = SPIN_LOCK_UNLOCKED; - -static inline void ack_r4ktimer(unsigned long newval) -{ - write_c0_compare(newval); -} - -/* - * There are a lot of conceptually broken versions of the MIPS timer interrupt - * handler floating around. This one is rather different, but the algorithm - * is provably more robust. - */ -unsigned long wtimer; -void mips_timer_interrupt(struct pt_regs *regs) -{ - int irq = 63; - unsigned long count; - int cpu = smp_processor_id(); - - irq_enter(cpu, irq); - kstat.irqs[cpu][irq]++; - - if (r4k_offset == 0) - goto null; - - do { - count = read_c0_count(); - timerhi += (count < timerlo); /* Wrap around */ - timerlo = count; - - kstat.irqs[0][irq]++; - do_timer(regs); - r4k_cur += r4k_offset; - ack_r4ktimer(r4k_cur); - - } while (((unsigned long)read_c0_count() - - r4k_cur) < 0x7fffffff); - - irq_exit(cpu, irq); - - if (softirq_pending(cpu)) - do_softirq(); - return; - -null: - ack_r4ktimer(0); -} - #ifdef CONFIG_PM void counter0_irq(int irq, void *dev_id, struct pt_regs *regs) { @@ -229,14 +180,16 @@ * "wait" is enabled, and we need to detect if the 32KHz isn't present * but requested......got it? :-) -- Dan */ -unsigned long cal_r4koff(void) +void __init au1xxx_time_init(void) { unsigned long count; unsigned long cpu_speed; unsigned long flags; unsigned long counter; + unsigned int est_freq; + unsigned long r4k_offset; - spin_lock_irqsave(&time_lock, flags); + printk("calculating r4koff... "); /* Power management cares if we don't have a 32KHz counter. */ @@ -294,75 +247,24 @@ count = cpu_speed / 2; no_au1xxx_32khz = 1; } + + /* let upper layer know the frequency */ mips_hpt_frequency = count; + // Equation: Baudrate = CPU / (SD * 2 * CLKDIV * 16) set_au1x00_uart_baud_base(cpu_speed / (2 * ((int)(au_readl(SYS_POWERCTRL)&0x03) + 2) * 16)); - spin_unlock_irqrestore(&time_lock, flags); - return (cpu_speed / HZ); -} - -/* This is for machines which generate the exact clock. */ -#define USECS_PER_JIFFY (1000000/HZ) -#define USECS_PER_JIFFY_FRAC (0x100000000*1000000/HZ&0xffffffff) - - -static unsigned long -div64_32(unsigned long v1, unsigned long v2, unsigned long v3) -{ - unsigned long r0; - do_div64_32(r0, v1, v2, v3); - return r0; -} -static unsigned long do_fast_cp0_gettimeoffset(void) -{ - u32 count; - unsigned long res, tmp; - unsigned long r0; - - /* Last jiffy when do_fast_gettimeoffset() was called. */ - static unsigned long last_jiffies=0; - unsigned long quotient; - - /* - * Cached "1/(clocks per usec)*2^32" value. - * It has to be recalculated once each jiffy. - */ - static unsigned long cached_quotient=0; - - tmp = jiffies; - - quotient = cached_quotient; - - if (tmp && last_jiffies != tmp) { - last_jiffies = tmp; - if (last_jiffies != 0) { - r0 = div64_32(timerhi, timerlo, tmp); - quotient = div64_32(USECS_PER_JIFFY, USECS_PER_JIFFY_FRAC, r0); - cached_quotient = quotient; - } - } - - /* Get last timer tick in absolute kernel time */ - count = read_c0_count(); - - /* .. relative to previous jiffy (32 bits is enough) */ - count -= timerlo; - - __asm__("multu\t%1,%2\n\t" - "mfhi\t%0" - :"=r" (res) - :"r" (count), - "r" (quotient)); - - /* - * Due to possible jiffies inconsistencies, we need to check - * the result so that we'll get a timer that is monotonic. - */ - if (res >= USECS_PER_JIFFY) - res = USECS_PER_JIFFY-1; + r4k_offset = cpu_speed / HZ; + printk("%08lx(%d)\n", r4k_offset, (int) r4k_offset); - return res; + //est_freq = 2*r4k_offset*HZ; + est_freq = r4k_offset*HZ; + est_freq += 5000; /* round */ + est_freq -= est_freq%10000; + printk("CPU frequency %d.%02d MHz\n", est_freq/1000000, + (est_freq%1000000)*100/1000000); + set_au1x00_speed(est_freq); + set_au1x00_lcd_clock(); // program the LCD clock } #ifdef CONFIG_PM @@ -386,30 +288,8 @@ void __init au1xxx_timer_setup(void) { - unsigned int est_freq; - extern unsigned long (*do_gettimeoffset)(void); extern void au1k_wait(void); - printk("calculating r4koff... "); - r4k_offset = cal_r4koff(); - printk("%08lx(%d)\n", r4k_offset, (int) r4k_offset); - - //est_freq = 2*r4k_offset*HZ; - est_freq = r4k_offset*HZ; - est_freq += 5000; /* round */ - est_freq -= est_freq%10000; - printk("CPU frequency %d.%02d MHz\n", est_freq/1000000, - (est_freq%1000000)*100/1000000); - set_au1x00_speed(est_freq); - set_au1x00_lcd_clock(); // program the LCD clock - - r4k_cur = (read_c0_count() + r4k_offset); - write_c0_compare(r4k_cur); - - /* no RTC on the pb1000 */ - xtime.tv_sec = 0; - xtime.tv_usec = 0; - #ifdef CONFIG_PM /* * setup counter 0, since it keeps ticking after a @@ -427,7 +307,6 @@ unsigned int c0_status; printk("WARNING: no 32KHz clock found.\n"); - do_gettimeoffset = do_fast_cp0_gettimeoffset; /* Ensure we get CPO_COUNTER interrupts. */ @@ -436,6 +315,8 @@ write_c0_status(c0_status); } else { + extern unsigned long (*do_gettimeoffset)(void); + while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S); au_writel(0, SYS_TOYWRITE); while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S); @@ -458,16 +339,5 @@ */ au1k_wait_ptr = au1k_wait; } - -#else - /* We have to do this here instead of in timer_init because - * the generic code in arch/mips/kernel/time.c will write - * over our function pointer. - */ - do_gettimeoffset = do_fast_cp0_gettimeoffset; #endif } - -void __init au1xxx_time_init(void) -{ -} diff -Nru linux/arch/mips/au1000/common/setup.c.orig linux/arch/mips/au1000/common/setup.c --- linux/arch/mips/au1000/common/setup.c.orig 2004-02-11 13:53:43.000000000 -0800 +++ linux/arch/mips/au1000/common/setup.c 2004-02-11 18:04:26.000000000 -0800 @@ -33,7 +33,6 @@ #include #include #include -#include #include #include @@ -57,7 +56,6 @@ extern struct ide_ops *ide_ops; #endif -extern struct rtc_ops no_rtc_ops; extern char * __init prom_getcmdline(void); extern void __init board_setup(void); extern void au1000_restart(char *); diff -Nru linux/arch/mips/au1000/common/int-handler.S.orig linux/arch/mips/au1000/common/int-handler.S --- linux/arch/mips/au1000/common/int-handler.S.orig 2002-08-05 16:53:30.000000000 -0700 +++ linux/arch/mips/au1000/common/int-handler.S 2004-02-11 18:04:26.000000000 -0800 @@ -33,8 +33,9 @@ andi a0, t0, CAUSEF_IP7 beq a0, zero, 1f - move a0, sp - jal mips_timer_interrupt + move a1, sp + li a0, 63 # sys timer irq is hardcoded at 63... + jal ll_timer_interrupt j ret_from_irq 1: diff -Nru linux/arch/mips/au1000/common/dbg_io.c.orig linux/arch/mips/au1000/common/dbg_io.c --- linux/arch/mips/au1000/common/dbg_io.c.orig 2003-06-06 10:22:26.000000000 -0700 +++ linux/arch/mips/au1000/common/dbg_io.c 2004-02-11 18:10:29.000000000 -0800 @@ -65,7 +65,7 @@ if (UART16550_READ(UART_MOD_CNTRL) != 0x3) { UART16550_WRITE(UART_MOD_CNTRL, 3); } - cal_r4koff(); + au1xxx_time_init(); /* disable interrupts */ UART16550_WRITE(UART_IER, 0); diff -Nru linux/arch/mips/config-shared.in.orig linux/arch/mips/config-shared.in