diff options
Diffstat (limited to 'arch/mips/mti-sead3/sead3-time.c')
| -rw-r--r-- | arch/mips/mti-sead3/sead3-time.c | 113 | 
1 files changed, 113 insertions, 0 deletions
diff --git a/arch/mips/mti-sead3/sead3-time.c b/arch/mips/mti-sead3/sead3-time.c new file mode 100644 index 00000000000..678d03d53c6 --- /dev/null +++ b/arch/mips/mti-sead3/sead3-time.c @@ -0,0 +1,113 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License.  See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2012 MIPS Technologies, Inc.  All rights reserved. + */ +#include <linux/init.h> + +#include <asm/cpu.h> +#include <asm/setup.h> +#include <asm/time.h> +#include <asm/irq.h> +#include <asm/mips-boards/generic.h> + +static int mips_cpu_timer_irq; +static int mips_cpu_perf_irq; + +static void mips_timer_dispatch(void) +{ +	do_IRQ(mips_cpu_timer_irq); +} + +static void mips_perf_dispatch(void) +{ +	do_IRQ(mips_cpu_perf_irq); +} + +static void __iomem *status_reg = (void __iomem *)0xbf000410; + +/* + * Estimate CPU frequency.  Sets mips_hpt_frequency as a side-effect. + */ +static unsigned int __init estimate_cpu_frequency(void) +{ +	unsigned int prid = read_c0_prid() & (PRID_COMP_MASK | PRID_IMP_MASK); +	unsigned int tick = 0; +	unsigned int freq; +	unsigned int orig; +	unsigned long flags; + +	local_irq_save(flags); + +	orig = readl(status_reg) & 0x2;		      /* get original sample */ +	/* wait for transition */ +	while ((readl(status_reg) & 0x2) == orig) +		; +	orig = orig ^ 0x2;			      /* flip the bit */ + +	write_c0_count(0); + +	/* wait 1 second (the sampling clock transitions every 10ms) */ +	while (tick < 100) { +		/* wait for transition */ +		while ((readl(status_reg) & 0x2) == orig) +			; +		orig = orig ^ 0x2;			      /* flip the bit */ +		tick++; +	} + +	freq = read_c0_count(); + +	local_irq_restore(flags); + +	mips_hpt_frequency = freq; + +	/* Adjust for processor */ +	if ((prid != (PRID_COMP_MIPS | PRID_IMP_20KC)) && +		(prid != (PRID_COMP_MIPS | PRID_IMP_25KF))) +		freq *= 2; + +	freq += 5000;	     /* rounding */ +	freq -= freq%10000; + +	return freq ; +} + +void read_persistent_clock(struct timespec *ts) +{ +	ts->tv_sec = 0; +	ts->tv_nsec = 0; +} + +static void __init plat_perf_setup(void) +{ +	if (cp0_perfcount_irq >= 0) { +		if (cpu_has_vint) +			set_vi_handler(cp0_perfcount_irq, mips_perf_dispatch); +		mips_cpu_perf_irq = MIPS_CPU_IRQ_BASE + cp0_perfcount_irq; +	} +} + +unsigned int get_c0_compare_int(void) +{ +	if (cpu_has_vint) +		set_vi_handler(cp0_compare_irq, mips_timer_dispatch); +	mips_cpu_timer_irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq; +	return mips_cpu_timer_irq; +} + +void __init plat_time_init(void) +{ +	unsigned int est_freq; + +	est_freq = estimate_cpu_frequency(); + +	pr_debug("CPU frequency %d.%02d MHz\n", (est_freq / 1000000), +		(est_freq % 1000000) * 100 / 1000000); + +	mips_scroll_message(); + +	plat_perf_setup(); +}  | 
