sim_time.c 2.5 KB
Newer Older
1 2 3 4 5 6 7
#include <linux/types.h>
#include <linux/init.h>
#include <linux/kernel_stat.h>
#include <linux/sched.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/mc146818rtc.h>
8
#include <linux/smp.h>
9
#include <linux/timex.h>
N
Nicolas Kaiser 已提交
10

11 12 13
#include <asm/hardirq.h>
#include <asm/div64.h>
#include <asm/cpu.h>
14
#include <asm/setup.h>
15
#include <asm/time.h>
N
Nicolas Kaiser 已提交
16
#include <asm/irq.h>
17 18 19 20 21 22 23 24 25 26 27
#include <asm/mc146818-time.h>
#include <asm/msc01_ic.h>

#include <asm/mips-boards/generic.h>
#include <asm/mips-boards/prom.h>
#include <asm/mips-boards/simint.h>


unsigned long cpu_khz;

/*
28
 * Estimate CPU frequency.  Sets mips_hpt_frequency as a side-effect
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
 */
static unsigned int __init estimate_cpu_frequency(void)
{
	unsigned int prid = read_c0_prid() & 0xffff00;
	unsigned int count;

#if 1
	/*
	 * hardwire the board frequency to 12MHz.
	 */

	if ((prid == (PRID_COMP_MIPS | PRID_IMP_20KC)) ||
	    (prid == (PRID_COMP_MIPS | PRID_IMP_25KF)))
		count = 12000000;
	else
		count =  6000000;
#else
	unsigned int flags;

	local_irq_save(flags);

	/* Start counter exactly on falling edge of update flag */
	while (CMOS_READ(RTC_REG_A) & RTC_UIP);
	while (!(CMOS_READ(RTC_REG_A) & RTC_UIP));

	/* Start r4k counter. */
	write_c0_count(0);

	/* Read counter exactly on falling edge of update flag */
	while (CMOS_READ(RTC_REG_A) & RTC_UIP);
	while (!(CMOS_READ(RTC_REG_A) & RTC_UIP));

	count = read_c0_count();

	/* restore interrupts */
	local_irq_restore(flags);
#endif

	mips_hpt_frequency = count;

	if ((prid != (PRID_COMP_MIPS | PRID_IMP_20KC)) &&
	    (prid != (PRID_COMP_MIPS | PRID_IMP_25KF)))
		count *= 2;

	count += 5000;    /* round */
	count -= count%10000;

	return count;
}

static int mips_cpu_timer_irq;

81
static void mips_timer_dispatch(void)
82
{
83
	do_IRQ(mips_cpu_timer_irq);
84 85 86
}


87
unsigned __cpuinit get_c0_compare_int(void)
88
{
89
#ifdef MSC01E_INT_BASE
90 91 92
	if (cpu_has_veic) {
		set_vi_handler(MSC01E_INT_CPUCTR, mips_timer_dispatch);
		mips_cpu_timer_irq = MSC01E_INT_BASE + MSC01E_INT_CPUCTR;
93 94

		return mips_cpu_timer_irq;
95
	}
96 97 98 99
#endif
	if (cpu_has_vint)
		set_vi_handler(cp0_compare_irq, mips_timer_dispatch);
	mips_cpu_timer_irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq;
100

101 102
	return mips_cpu_timer_irq;
}
103

104 105
void __init plat_time_init(void)
{
106
	unsigned int est_freq;
107 108 109 110 111 112 113 114 115 116

	/* Set Data mode - binary. */
	CMOS_WRITE(CMOS_READ(RTC_CONTROL) | RTC_DM_BINARY, RTC_CONTROL);

	est_freq = estimate_cpu_frequency();

	printk(KERN_INFO "CPU frequency %d.%02d MHz\n", est_freq / 1000000,
	       (est_freq % 1000000) * 100 / 1000000);

	cpu_khz = est_freq / 1000;
117
}