X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fmips%2Fau1000%2Fcommon%2Ftime.c;h=f74d66a58a21a51c8dc2915c8e741fc0b500440a;hb=9464c7cf61b9433057924c36e6e02f303a00e768;hp=f58f454cdc8cf53447b2bbc618f01d4b63047811;hpb=daddc0d38b3571bed170afa273a49a0eba090c1e;p=linux-2.6.git diff --git a/arch/mips/au1000/common/time.c b/arch/mips/au1000/common/time.c index f58f454cd..f74d66a58 100644 --- a/arch/mips/au1000/common/time.c +++ b/arch/mips/au1000/common/time.c @@ -38,18 +38,18 @@ #include #include #include +#include +#include #include #include #include -#include #include #include #include #include -extern void startup_match20_interrupt(void); extern void do_softirq(void); extern volatile unsigned long wall_jiffies; unsigned long missed_heart_beats = 0; @@ -57,18 +57,21 @@ 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 */ int no_au1xxx_32khz; -void (*au1k_wait_ptr)(void); +extern int allow_au1k_wait; /* default off for CP0 Counter */ /* 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); +#if HZ < 100 || HZ > 1000 +#error "unsupported HZ value! Must be in [100,1000]" +#endif +#define MATCH20_INC (328*100/HZ) /* magic number 328 is for HZ=100... */ +extern void startup_match20_interrupt(irqreturn_t (*handler)(int, void *, struct pt_regs *)); static unsigned long last_pc0, last_match20; #endif -static spinlock_t time_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(time_lock); static inline void ack_r4ktimer(unsigned long newval) { @@ -99,6 +102,9 @@ void mips_timer_interrupt(struct pt_regs *regs) kstat_this_cpu.irqs[irq]++; do_timer(regs); +#ifndef CONFIG_SMP + update_process_times(user_mode(regs)); +#endif r4k_cur += r4k_offset; ack_r4ktimer(r4k_cur); @@ -110,20 +116,20 @@ void mips_timer_interrupt(struct pt_regs *regs) null: ack_r4ktimer(0); + irq_exit(); } #ifdef CONFIG_PM -void counter0_irq(int irq, void *dev_id, struct pt_regs *regs) +irqreturn_t counter0_irq(int irq, void *dev_id, struct pt_regs *regs) { unsigned long pc0; int time_elapsed; static int jiffie_drift = 0; - kstat.irqs[0][irq]++; if (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20) { /* should never happen! */ - printk(KERN_WARNING "counter 0 w status eror\n"); - return; + printk(KERN_WARNING "counter 0 w status error\n"); + return IRQ_NONE; } pc0 = au_readl(SYS_TOYREAD); @@ -137,6 +143,9 @@ void counter0_irq(int irq, void *dev_id, struct pt_regs *regs) while (time_elapsed > 0) { do_timer(regs); +#ifndef CONFIG_SMP + update_process_times(user_mode(regs)); +#endif time_elapsed -= MATCH20_INC; last_match20 += MATCH20_INC; jiffie_drift++; @@ -153,7 +162,12 @@ void counter0_irq(int irq, void *dev_id, struct pt_regs *regs) if (jiffie_drift >= 999) { jiffie_drift -= 999; do_timer(regs); /* increment jiffies by one */ +#ifndef CONFIG_SMP + update_process_times(user_mode(regs)); +#endif } + + return IRQ_HANDLED; } /* When we wakeup from sleep, we have to "catch up" on all of the @@ -271,7 +285,7 @@ unsigned long cal_r4koff(void) cpu_speed = count * 2; } #else - cpu_speed = (au_readl(SYS_CPUPLL) & 0x0000003f) * + cpu_speed = (au_readl(SYS_CPUPLL) & 0x0000003f) * AU1000_SRC_CLK; count = cpu_speed / 2; #endif @@ -294,8 +308,7 @@ unsigned long cal_r4koff(void) /* This is for machines which generate the exact clock. */ #define USECS_PER_JIFFY (1000000/HZ) -#define USECS_PER_JIFFY_FRAC (0x100000000*1000000/HZ&0xffffffff) - +#define USECS_PER_JIFFY_FRAC (0x100000000LL*1000000/HZ&0xffffffff) static unsigned long div64_32(unsigned long v1, unsigned long v2, unsigned long v3) @@ -342,12 +355,12 @@ static unsigned long do_fast_cp0_gettimeoffset(void) __asm__("multu\t%1,%2\n\t" "mfhi\t%0" - :"=r" (res) - :"r" (count), - "r" (quotient)); + : "=r" (res) + : "r" (count), "r" (quotient) + : "hi", "lo", GCC_REG_ACCUM); /* - * Due to possible jiffies inconsistencies, we need to check + * 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) @@ -366,8 +379,8 @@ static unsigned long do_fast_pm_gettimeoffset(void) au_sync(); offset = pc0 - last_pc0; if (offset > 2*MATCH20_INC) { - printk("huge offset %x, last_pc0 %x last_match20 %x pc0 %x\n", - (unsigned)offset, (unsigned)last_pc0, + printk("huge offset %x, last_pc0 %x last_match20 %x pc0 %x\n", + (unsigned)offset, (unsigned)last_pc0, (unsigned)last_match20, (unsigned)pc0); } offset = (unsigned long)((offset * 305) / 10); @@ -379,17 +392,16 @@ void au1xxx_timer_setup(struct irqaction *irq) { 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 = 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, + 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 @@ -397,10 +409,6 @@ void au1xxx_timer_setup(struct irqaction *irq) 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 @@ -436,18 +444,18 @@ void au1xxx_timer_setup(struct irqaction *irq) au_sync(); while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20); - /* setup match20 to interrupt once every 10ms */ + /* setup match20 to interrupt once every HZ */ last_pc0 = last_match20 = au_readl(SYS_TOYREAD); au_writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2); au_sync(); while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20); - startup_match20_interrupt(); + startup_match20_interrupt(counter0_irq); do_gettimeoffset = do_fast_pm_gettimeoffset; /* We can use the real 'wait' instruction. */ - au1k_wait_ptr = au1k_wait; + allow_au1k_wait = 1; } #else