--- zzzz-none-000/linux-2.4.17/arch/mips/mips-boards/generic/time.c 2001-09-09 17:43:02.000000000 +0000 +++ sangam-fb-322/linux-2.4.17/arch/mips/mips-boards/generic/time.c 2004-12-16 10:39:50.000000000 +0000 @@ -2,6 +2,13 @@ * Carsten Langgaard, carstenl@mips.com * Copyright (C) 1999,2000 MIPS Technologies, Inc. All rights reserved. * + * Jeff Harrell, jharrell@ti.com + * Copyright (C) 2000-2002 Texas Instruments, Inc. All rights reserved. + * + * Nick Zajerko-McKee, nmckee@telogy.com + * Copyright (C) 2002 Telogy Networks, Inc All rights reserved + * + * * ######################################################################## * * This program is free software; you can distribute it and/or modify it @@ -23,7 +30,9 @@ * */ +#include #include +#include #include #include #include @@ -31,21 +40,56 @@ #include #include +#include #include +#define _INCLUDED_FROM_TIME_C +#include +#include +#include #include #include #include #include -extern volatile unsigned long wall_jiffies; +#if defined(CONFIG_MIPS_AVALANCHE_IIC) +extern void iic_write_data(unsigned char addr,unsigned char data); + +/* AVALANCHE I2C routines */ +extern unsigned char iic_read_byte(unsigned int dtype, unsigned int dev, unsigned int adr); +extern unsigned char iic_write_byte(unsigned char addr, unsigned char data); +extern int iic_writeb_addr(unsigned int dtype, unsigned int dev, unsigned int adr, unsigned int dat); +extern void init_iic(unsigned long cpu_freq); +#endif + +#if defined(CONFIG_MIPS_AVALANCHE_SOC ) +#include + +/* AVALANCHE 7-segment display variables */ +unsigned long av_heartbeat_count; + +#if defined(CONFIG_MIPS_AVALANCHE_7SEG) /* P S P L 5 1 t i t a n*/ +static unsigned char seven_segarray[] = {0x66,0x5b,0x66,0x0e,0x5b,0x03,0x0f,0x01,0x0f,0x3d,0x15}; +#endif + +/* AVALANCHE Global cpu frequency variable */ +unsigned long cpu_freq; +unsigned int mips_counter_frequency = 0; + +#else + static long last_rtc_update = 0; +#endif /* CONFIG_MIPS_AVALANCHE_SOC */ + +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 */ +unsigned long r4k_offset; /* Amount to increment compare reg each time */ +unsigned long r4k_cur; /* What counter should be at next timer irq */ extern rwlock_t xtime_lock; +static unsigned int reschedule_int = 0; #define ALLINTS (IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5) @@ -55,18 +99,46 @@ #if defined(CONFIG_MIPS_MALTA) static char display_string[] = " LINUX ON MALTA "; #endif -static unsigned int display_count = 0; -#define MAX_DISPLAY_COUNT (sizeof(display_string) - 8) -static unsigned int timer_tick_count=0; +#if defined(CONFIG_MIPS_AVALANCHE_SOC ) +#if defined(CONFIG_MIPS_AVALANCHE_7SEG) +#define MAX_AVALANCHE_DISPLAY_COUNT = sizeof(seven_segarray); +#endif +#else +static unsigned int display_count = 0; +#define MAX_DISPLAY_COUNT (sizeof(display_string) - 8) +static unsigned int timer_tick_count=0; +#endif /* CONFIG_MIPS_AVALANCHE_SOC */ +#ifndef CONFIG_HIGH_RES_TIMERS /* TEST */ +#define TMR_OFFSET 625000 +#define MAX_TICK 800 +#else +#define TMR_OFFSET 62500 +#define MAX_TICK 8000 +#endif static inline void ack_r4ktimer(unsigned long newval) { write_32bit_cp0_register(CP0_COMPARE, newval); } +#ifndef CONFIG_HIGH_RES_TIMERS + +/* Number of usecs that the last interrupt was delayed */ +static int delay_at_last_interrupt; +#endif /* CONFIG_HIGH_RES_TIMERS */ +#ifndef CONFIG_HIGH_RES_TIMERS +/* Number of usecs that the last interrupt was delayed */ +static int delay_at_last_interrupt; + +#endif /* CONFIG_HIGH_RES_TIMERS */ + + +#if defined(CONFIG_MIPS_AVALANCHE_SOC ) +/* nothing */ +#else /* * In order to set the CMOS clock precisely, set_rtc_mmss has to be * called 500 ms after the second nowtime has started, because when @@ -126,6 +198,9 @@ return retval; } +#endif /* CONFIG_MIPS_AVALANCHE_SOC */ + + /* * There are a lot of conceptually broken versions of the MIPS timer interrupt * handler floating around. This one is rather different, but the algorithm @@ -133,32 +208,55 @@ */ void mips_timer_interrupt(struct pt_regs *regs) { + int cpu = smp_processor_id(); int irq = 7; if (r4k_offset == 0) goto null; + irq_enter(cpu, irq); do { - kstat.irqs[0][irq]++; + kstat.irqs[cpu][irq]++; +#ifdef CONFIG_HIGH_RES_TIMERS + reschedule_int = 1; +#endif do_timer(regs); +#ifdef CONFIG_HIGH_RES_TIMERS + if (!new_jiffie()) + { +#endif +#if defined (CONFIG_MIPS_EVM3) + if (xtime.tv_usec < 100000/HZ) + { + if(avalanche_heartbeat_count >= SEVEN_SEG_MAX_POS) + avalanche_heartbeat_count = 0; + iic_write_data(SEVEN_SEGMENT_DISP, seven_segarray[evm3_heartbeat_count]); + avalanche_heartbeat_count++; + } +#endif /* CONFIG_MIPS_EVM3 */ + +#if defined(CONFIG_MIPS_AVALANCHE_SOC) + /*nothing*/ +#else /* Historical comment/code: - * RTC time of day s updated approx. every 11 - * minutes. Because of how the numbers work out + * RTC time of day s updated approx. every 11 + * minutes. Because of how the numbers work out * we need to make absolutely sure we do this update - * within 500ms before the * next second starts, + * within 500ms before the * next second starts, * thus the following code. */ read_lock(&xtime_lock); - if ((time_status & STA_UNSYNC) == 0 - && xtime.tv_sec > last_rtc_update + 660 - && xtime.tv_usec >= 500000 - (tick >> 1) - && xtime.tv_usec <= 500000 + (tick >> 1)) + if ((time_status & STA_UNSYNC) == 0 + && xtime.tv_sec > last_rtc_update + 660 + && xtime.tv_usec >= 500000 - (tick >> 1) + && xtime.tv_usec <= 500000 + (tick >> 1)) { if (set_rtc_mmss(xtime.tv_sec) == 0) last_rtc_update = xtime.tv_sec; else /* do it again in 60 s */ - last_rtc_update = xtime.tv_sec - 600; + last_rtc_update = xtime.tv_sec - 600; + } read_unlock(&xtime_lock); if ((timer_tick_count++ % HZ) == 0) { @@ -166,12 +264,27 @@ if (display_count == MAX_DISPLAY_COUNT) display_count = 0; } - +#endif /* CONFIG_MIPS_AVALANCHE_SOC */ +#ifdef CONFIG_HIGH_RES_TIMERS + } + else + { + jiffies_intr = 0; + } + if(reschedule_int) + { +#endif r4k_cur += r4k_offset; ack_r4ktimer(r4k_cur); - +#ifdef CONFIG_HIGH_RES_TIMERS + } +#endif } while (((unsigned long)read_32bit_cp0_register(CP0_COUNT) - r4k_cur) < 0x7fffffff); + irq_exit(cpu, irq); + + if (softirq_pending(cpu)) + do_softirq(); return; @@ -179,14 +292,337 @@ ack_r4ktimer(0); } -/* + +#ifdef CONFIG_HIGH_RES_TIMERS +/* + * ALL_PERIODIC mode is used if we MUST support the NMI watchdog. In this + * case we must continue to provide interrupts even if they are not serviced. + * In this mode, we leave the chip in periodic mode programmed to interrupt + * every jiffie. This is done by, for short intervals, programming a short + * time, waiting till it is loaded and then programming the 1/HZ. The chip + * will not load the 1/HZ count till the short count expires. If the last + * interrupt was programmed to be short, we need to program another short + * to cover the remaining part of the jiffie and can then just leave the + * chip alone. + */ +IF_ALL_PERIODIC(static int last_was_long = 0;) +int _schedule_next_int(unsigned long jiffie_f,long sub_jiffie_in, int always) +{ + long sub_jiff_offset = 0; + unsigned long r4k_compare; + IF_ALL_PERIODIC( if ((sub_jiffie_in == -1) && last_was_long) return 0); + /* + * First figure where we are in time. + * A note on locking. We are under the timerlist_lock here. This + * means that interrupts are off already, so don't use irq versions. + */ + if_SMP( read_lock(&xtime_lock)); + sub_jiff_offset = quick_update_jiffies_sub(jiffie_f); + if_SMP( read_unlock(&xtime_lock)); + + if ((IF_ALL_PERIODIC( last_was_long =) (sub_jiffie_in == -1 ))) { + sub_jiff_offset = cycles_per_jiffies - sub_jiff_offset; + }else{ + sub_jiff_offset = sub_jiffie_in - sub_jiff_offset; + } + + /* + * If time is already passed, just return saying so. + */ + if (! always && (sub_jiff_offset < high_res_test_val)){ + IF_ALL_PERIODIC( last_was_long = 0); + return 1; + } + /* + * This handles the case we're we are in negative offset or + * that the offset is much bigger than a jiffie (shouldn't happen) + * or for the case that the jiffy offset is very very small + */ + if((sub_jiff_offset > r4k_offset) || (sub_jiff_offset < MIPS_GUARD_TIME)) + { +#if 0 + printk("\nERROR %ld value in schedule_next_int() %lu\n",sub_jiff_offset, (unsigned long)read_32bit_cp0_register(CP0_COUNT)); +#endif + return 1; + } + reschedule_int = 0; + r4k_compare= (unsigned long)read_32bit_cp0_register(CP0_COUNT); + r4k_compare += sub_jiff_offset; + + /* + * Handle the case we're we are close to a "normal interrupt" + * by changing it to occur in the future + */ + if(r4k_compare > r4k_cur) + { + r4k_cur += r4k_offset; + } + ack_r4ktimer(r4k_compare); + return 0; +} + +#define DEBUG_HIGH_RES_TIMERS 0 +void __init hrtimer_init(void) +{ +#if DEBUG_HIGH_RES_TIMERS + unsigned long i = 10000; +#endif + /* + * The init_hrtimers macro is in the choosen support package + * depending on the clock source. + */ + init_hrtimers(); + printk("Initialized High Resolution timers\n"); +#if DEBUG_HIGH_RES_TIMERS + printk("arch_to_usec = %lu\n",arch_to_usec); + printk("usec_to_arch = %lu\n",usec_to_arch); + printk("arch_to_nsec = %lu\n",arch_to_nsec); + printk("nsec_to_arch = %lu\n",nsec_to_arch); + printk("cycles_per_jiffies = %lu\n",cycles_per_jiffies); + printk("a->n = %u\n",arch_cycles_to_nsec(i)); + printk("n->a = %u\n",nsec_to_arch_cycles(i)); + printk("a->u = %u\n",arch_cycles_to_usec(i)); + printk("u->a = %u\n",usec_to_arch_cycles(i)); + + +#endif +} +#else +#define hrtimer_init() +#endif /* ! CONFIG_HIGH_RES_TIMERS */ + +#if defined(CONFIG_AVALANCHE_CPU_FREQUENCY_SWITCHING) +#include + +/*------------------------------------------------------------------------------------------*\ +\*------------------------------------------------------------------------------------------*/ +unsigned int current_cpu_frequency; + +/*------------------------------------------------------------------------------------------*\ +\*------------------------------------------------------------------------------------------*/ +int change_cpu_frequency(unsigned int new_cpu_freq) { + unsigned int est_freq; + + /*--------------------------------------------------------------------------------------*\ + \*--------------------------------------------------------------------------------------*/ + printk("change_cpu_frequency: to %u Hz\n", new_cpu_freq); + avalanche_clkc_set_freq(CLKC_MIPS, new_cpu_freq); + new_cpu_freq = avalanche_clkc_get_freq(CLKC_MIPS); + current_cpu_frequency = new_cpu_freq; + printk("change_cpu_frequency: changed to %u Hz\n", new_cpu_freq); + + /*--------------------------------------------------------------------------------------*\ + \*--------------------------------------------------------------------------------------*/ + printk("calculating r4koff... "); + r4k_offset = current_cpu_frequency / 2 / HZ; + + printk("%08lx(%d)\n", r4k_offset, (int) r4k_offset); + + est_freq = 2*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); + hrtimer_init(); + r4k_cur = (read_32bit_cp0_register(CP0_COUNT) + r4k_offset); + + write_32bit_cp0_register(CP0_COMPARE, r4k_cur); + change_cp0_status(ST0_IM, ALLINTS); + + return new_cpu_freq; + +} +/*------------------------------------------------------------------------------------------*\ +\*------------------------------------------------------------------------------------------*/ +unsigned int (*p_dsp_voltage_set)(unsigned int); +EXPORT_SYMBOL(p_dsp_voltage_set); + +/*------------------------------------------------------------------------------------------*\ +\*------------------------------------------------------------------------------------------*/ +int clocks_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data) { + int len; + + sprintf(page, "System: %u Hz MIPS: %u Hz USB: %u Hz DSP: %u Hz VBUS: %u Hz ", + avalanche_clkc_get_freq(CLKC_SYS), + avalanche_clkc_get_freq(CLKC_MIPS), + avalanche_clkc_get_freq(CLKC_USB), + avalanche_clkc_get_freq(CLKC_ADSLSS), + avalanche_get_vbus_freq() + ); + + len = strlen(page); + + if(p_dsp_voltage_set) + sprintf(page + len, " Core %u mV\n", (p_dsp_voltage_set)(0)); + else + sprintf(page + len, "\n"); + + len = strlen(page); + + if (len <= off+count) *eof = 1; + *start = page + off; + len -= off; + if (len>count) len = count; + if (len<0) len = 0; + return len; +} + +/*------------------------------------------------------------------------------------------*\ +\*------------------------------------------------------------------------------------------*/ +int clocks_write_proc (struct file *file, const char *buffer, unsigned long count, void *data) { + int clk_id, new_clk; + char *Name = NULL; + /*--- printk("clocks_write_proc: buffer(%u bytes)='%.*s'\n", (int)count, (int)count, buffer); ---*/ + if(!strncmp(buffer, "System", sizeof("System") - 1)) { + clk_id = CLKC_SYS; + Name = "System"; + buffer += sizeof("System") - 1; + } else if(!strncmp(buffer, "MIPS", sizeof("MIPS") - 1)) { + clk_id = CLKC_MIPS; + Name = "MIPS"; + buffer += sizeof("MIPS") - 1; + } else if(!strncmp(buffer, "USB", sizeof("USB") - 1)) { + clk_id = CLKC_USB; + Name = "USB"; + buffer += sizeof("USB") - 1; + } else if(!strncmp(buffer, "DSP", sizeof("DSP") - 1)) { + clk_id = CLKC_ADSLSS; + Name = "DSP"; + buffer += sizeof("DSP") - 1; + } else if(!strncmp(buffer, "Core", sizeof("Core") - 1)) { + unsigned int ret; + buffer += sizeof("Core") - 1; + if(p_dsp_voltage_set) { + unsigned int millivolt; + while(*buffer && (*buffer == ' ' || *buffer == '\t')) + buffer++; + millivolt = simple_strtol(buffer, NULL, 0); + ret = (*p_dsp_voltage_set)(millivolt); + printk("Core is set to %u mV (want %u)\n", ret, millivolt); + return count; + } + printk("don't know how to set the core\n"); + return count; + } else { + printk("clocks_write_proc: unknown clock '%.*s'\n", (int)count, buffer); + return count; + } + + while(*buffer && (*buffer == ' ' || *buffer == '\t')) + buffer++; + new_clk = simple_strtol(buffer, NULL, 0); + + switch(clk_id) { + case CLKC_USB: + printk("clocks_write_proc: change of USB Clock illegal\n"); + return count; + case CLKC_ADSLSS: + avalanche_clkc_set_freq(clk_id, new_clk), + new_clk = avalanche_clkc_get_freq(clk_id); + break; + case CLKC_SYS: +/*------------------------------------------------------------------------------------------*\ + System: in=25000000 MHz prediv=1 mul=4 postdiv=1 = 100000000 MHz USB : in=100000000 MHz prediv=25 mul=12 postdiv=1 = 48000000 MHz + System: in=25000000 MHz prediv=1 mul=6 postdiv=5 = 30000000 MHz USB : in=30000000 MHz prediv=5 mul=8 postdiv=1 = 48000000 MHz + System: in=25000000 MHz prediv=1 mul=7 postdiv=3 = 58333333 MHz USB : in=58333333 MHz prediv=17 mul=14 postdiv=1 = 48039208 MHz + System: in=25000000 MHz prediv=1 mul=8 postdiv=5 = 40000000 MHz USB : in=40000000 MHz prediv=10 mul=12 postdiv=1 = 48000000 MHz + System: in=25000000 MHz prediv=1 mul=11 postdiv=3 = 91666666 MHz USB : in=91666666 MHz prediv=21 mul=11 postdiv=1 = 48015869 MHz + System: in=25000000 MHz prediv=1 mul=11 postdiv=7 = 39285714 MHz USB : in=39285714 MHz prediv=9 mul=11 postdiv=1 = 48015869 MHz + System: in=25000000 MHz prediv=1 mul=11 postdiv=9 = 30555555 MHz USB : in=30555555 MHz prediv=7 mul=11 postdiv=1 = 48015869 MHz + System: in=25000000 MHz prediv=1 mul=12 postdiv=5 = 60000000 MHz USB : in=60000000 MHz prediv=1 mul=4 postdiv=5 = 48000000 MHz + System: in=25000000 MHz prediv=1 mul=13 postdiv=4 = 81250000 MHz USB : in=81250000 MHz prediv=11 mul=13 postdiv=2 = 48011359 MHz + System: in=25000000 MHz prediv=1 mul=13 postdiv=8 = 40625000 MHz USB : in=40625000 MHz prediv=11 mul=13 postdiv=1 = 48011353 MHz + System: in=25000000 MHz prediv=1 mul=13 postdiv=11 = 29545454 MHz USB : in=29545454 MHz prediv=8 mul=13 postdiv=1 = 48011353 MHz + System: in=25000000 MHz prediv=1 mul=14 postdiv=3 = 116666666 MHz USB : in=116666666 MHz prediv=17 mul=14 postdiv=2 = 48039215 MHz + System: in=25000000 MHz prediv=1 mul=14 postdiv=6 = 58333333 MHz USB : in=58333333 MHz prediv=17 mul=14 postdiv=1 = 48039208 MHz + System: in=25000000 MHz prediv=3 mul=11 postdiv=1 = 91666663 MHz USB : in=91666663 MHz prediv=21 mul=11 postdiv=1 = 48015869 MHz + System: in=25000000 MHz prediv=3 mul=11 postdiv=3 = 30555554 MHz USB : in=30555554 MHz prediv=7 mul=11 postdiv=1 = 48015869 MHz + System: in=25000000 MHz prediv=3 mul=12 postdiv=1 = 99999996 MHz USB : in=99999996 MHz prediv=25 mul=12 postdiv=1 = 47999988 MHz + System: in=25000000 MHz prediv=3 mul=14 postdiv=1 = 116666662 MHz USB : in=116666662 MHz prediv=17 mul=14 postdiv=2 = 48039208 MHz + System: in=25000000 MHz prediv=3 mul=14 postdiv=2 = 58333331 MHz USB : in=58333331 MHz prediv=17 mul=14 postdiv=1 = 48039208 MHz + System: in=25000000 MHz prediv=4 mul=13 postdiv=2 = 40625000 MHz USB : in=40625000 MHz prediv=11 mul=13 postdiv=1 = 48011353 MHz + System: in=25000000 MHz prediv=5 mul=6 postdiv=1 = 30000000 MHz USB : in=30000000 MHz prediv=5 mul=8 postdiv=1 = 48000000 MHz + System: in=25000000 MHz prediv=5 mul=12 postdiv=1 = 60000000 MHz USB : in=60000000 MHz prediv=15 mul=12 postdiv=1 = 48000000 MHz + System: in=25000000 MHz prediv=5 mul=12 postdiv=2 = 30000000 MHz USB : in=30000000 MHz prediv=5 mul=8 postdiv=1 = 48000000 MHz + System: in=25000000 MHz prediv=6 mul=14 postdiv=1 = 58333324 MHz USB : in=58333324 MHz prediv=17 mul=14 postdiv=1 = 48039208 MHz + System: in=25000000 MHz prediv=7 mul=11 postdiv=1 = 39285708 MHz USB : in=39285708 MHz prediv=3 mul=11 postdiv=3 = 48015865 MHz + System: in=25000000 MHz prediv=7 mul=11 postdiv=1 = 39285708 MHz USB : in=39285708 MHz prediv=9 mul=11 postdiv=1 = 48015858 MHz + System: in=25000000 MHz prediv=8 mul=13 postdiv=1 = 40625000 MHz USB : in=40625000 MHz prediv=11 mul=13 postdiv=1 = 48011353 MHz + System: in=25000000 MHz prediv=9 mul=11 postdiv=1 = 30555547 MHz USB : in=30555547 MHz prediv=7 mul=11 postdiv=1 = 48015858 MHz + System: in=25000000 MHz prediv=10 mul=12 postdiv=1 = 30000000 MHz USB : in=30000000 MHz prediv=5 mul=8 postdiv=1 = 48000000 MHz + System: in=25000000 MHz prediv=11 mul=13 postdiv=1 = 29545451 MHz USB : in=29545451 MHz prediv=8 mul=13 postdiv=1 = 48011353 MHz +\*------------------------------------------------------------------------------------------*/ + switch(new_clk) { + case 150000000: + case 125000000: + case 116666666: + case 100000000: + case 91666666: + case 81250000: + case 60000000: + case 58333333: + case 40000000: + case 30000000: + break; + default: + printk("/proc/clocks: legal System Values: (150000000) 125000000 116666666 100000000 91666666 81250000 60000000 58333333 40000000 30000000\n"); + return count; + } + avalanche_clkc_set_freq(clk_id, new_clk), + new_clk = avalanche_clkc_get_freq(clk_id); + avalanche_set_vbus_freq(avalanche_clkc_get_freq(CLKC_VBUS)); + /*--- avalanche_vbus_freq = new_clk / 2; ---*/ + avalanche_clkc_set_freq(CLKC_USB, 48000000), + printk("USB: %u Hz ", avalanche_clkc_get_freq(CLKC_USB)); +#if defined(CONFIG_SERIAL_CONSOLE) + serial_console_setup(NULL, NULL); +#endif /*--- #if defined(CONFIG_SERIAL_CONSOLE) ---*/ + break; + case CLKC_MIPS: + new_clk = change_cpu_frequency(new_clk); + break; + } + printk("%s clock changed to %u Hz\n", Name ? Name : "unknown", new_clk); + return count; +} + +#endif /*--- #if defined(CONFIG_AVALANCHE_CPU_FREQUENCY_SWITCHING) ---*/ + +/*------------------------------------------------------------------------------------------*\ +\*------------------------------------------------------------------------------------------*/ + +/* * Figure out the r4k offset, the amount to increment the compare - * register for each time tick. + * register for each time tick. * Use the RTC to calculate offset. */ static unsigned long __init cal_r4koff(void) { unsigned long count; + +#if defined(CONFIG_MIPS_AVALANCHE_SOC ) + unsigned char sec; + char *cpu_freq_ptr; + + cpu_freq_ptr = prom_getenv("cpufrequency"); + if(!cpu_freq_ptr) + { + cpu_freq = CONFIG_CPU_FREQUENCY_AVALANCHE * 1000000 ; + } + else + { + cpu_freq = simple_strtol(cpu_freq_ptr,NULL,0); + } + + sec = 0; + count = cpu_freq / 2; + +#if defined(CONFIG_MIPS_AVALANCHE_IIC) + init_iic(cpu_freq); +#endif + +#else /* !CONFIG_MIPS_AVALANCHE_SOC */ unsigned int flags; __save_and_cli(flags); @@ -207,12 +643,52 @@ /* restore interrupts */ __restore_flags(flags); +#endif /* CONFIG_MIPS_AVALANCHE_SOC */ +#if defined(CONFIG_AVALANCHE_CPU_FREQUENCY_SWITCHING) + current_cpu_frequency = cpu_freq; +#endif /*--- #if defined(CONFIG_AVALANCHE_CPU_FREQUENCY_SWITCHING) ---*/ return (count / HZ); } static unsigned long __init get_mips_time(void) { unsigned int year, mon, day, hour, min, sec; + +#if 0 + unsigned char clkdat[8]; + int regnum; + + for(regnum=0; regnum < 8; regnum++) + { + clkdat[regnum] = iic_read_byte(I2C_RTC,EVM3_RTC_I2C_ADDR,regnum); + } + + sec = (clkdat[0] & 0xf); + sec += (((clkdat[0] >> 4) & 0x7) * 10); + min = (clkdat[1] & 0xf); + min += (((clkdat[1] >> 4) & 0x7) * 10); + hour = (clkdat[2] & 0xf); + hour += (((clkdat[2] >> 4) & 0x3) * 10); + day = (clkdat[4] & 0xf); + day += (((clkdat[4] >> 4) & 0x3) * 10); + mon = (clkdat[5] & 0xf); + mon += (((clkdat[5] >> 4) & 0x1) * 10); + year = (clkdat[6] & 0xf); + year += (((clkdat[6] >> 4) & 0xf) * 10); + + /* check suraj */ +#else + +#if defined(CONFIG_MIPS_AVALANCHE_SOC) + year=2002; + mon=9; + day=8; + hour=12; + min=0; + sec=0; + return mktime(year, mon, day, hour, min, sec); +#else /* !CONFIG_MIPS_AVALANCHE_SOC */ + unsigned char save_control; save_control = CMOS_READ(RTC_CONTROL); @@ -230,7 +706,7 @@ if ((hour & 0xf) == 0xc) hour &= 0x80; if (hour & 0x80) - hour = (hour & 0xf) + 12; + hour = (hour & 0xf) + 12; } day = CMOS_READ(RTC_DAY_OF_MONTH); mon = CMOS_READ(RTC_MONTH); @@ -243,24 +719,30 @@ year += 100; return mktime(year, mon, day, hour, min, sec); + +#endif /* CONFIG_MIPS_AVALANCHE_SOC */ +#endif } void __init time_init(void) { unsigned int est_freq, flags; +#if !defined(CONFIG_MIPS_AVALANCHE_SOC) /* Set Data mode - binary. */ CMOS_WRITE(CMOS_READ(RTC_CONTROL) | RTC_DM_BINARY, RTC_CONTROL); +#endif printk("calculating r4koff... "); r4k_offset = cal_r4koff(); printk("%08lx(%d)\n", r4k_offset, (int) r4k_offset); - est_freq = 2*r4k_offset*HZ; + est_freq = 2*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); + hrtimer_init(); r4k_cur = (read_32bit_cp0_register(CP0_COUNT) + r4k_offset); write_32bit_cp0_register(CP0_COMPARE, r4k_cur); @@ -275,10 +757,17 @@ /* This is for machines which generate the exact clock. */ #define USECS_PER_JIFFY (1000000/HZ) -#define USECS_PER_JIFFY_FRAC ((1000000 << 32) / HZ & 0xffffffff) +#define USECS_PER_JIFFY_FRAC ((u32)((1000000ULL << 32) / HZ)) /* Cycle counter value at the previous timer interrupt.. */ - +#ifdef CONFIG_HIGH_RES_TIMERS +static unsigned long do_fast_gettimeoffset(void) +{ + long tmp = quick_get_cpuctr(); + long rtn = arch_cycles_to_usec(tmp + sub_jiffie()); + return rtn; +} +#else static unsigned int timerhi = 0, timerlo = 0; /* @@ -333,8 +822,7 @@ :"r" (timerhi), "m" (timerlo), "r" (tmp), - "r" (USECS_PER_JIFFY) - :"$1"); + "r" (USECS_PER_JIFFY)); cached_quotient = quotient; #endif } @@ -352,7 +840,7 @@ "r" (quotient)); /* - * 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) @@ -360,6 +848,7 @@ return res; } +#endif /* CONFIG_HIGH_RES_TIMERS */ void do_gettimeofday(struct timeval *tv) { @@ -378,8 +867,8 @@ read_unlock_irqrestore (&xtime_lock, flags); - if (tv->tv_usec >= 1000000) { - tv->tv_usec -= 1000000; + if (tv->tv_usec >= USEC_PER_SEC) { + tv->tv_usec -= USEC_PER_SEC; tv->tv_sec++; } } @@ -396,7 +885,7 @@ tv->tv_usec -= do_fast_gettimeoffset(); if (tv->tv_usec < 0) { - tv->tv_usec += 1000000; + tv->tv_usec += USEC_PER_SEC; tv->tv_sec--; } @@ -408,3 +897,7 @@ write_unlock_irq (&xtime_lock); } + + + +