diff options
author | Steven J. Hill <sjhill@mips.com> | 2012-12-07 03:51:04 +0000 |
---|---|---|
committer | John Crispin <blogic@openwrt.org> | 2013-02-17 01:25:21 +0100 |
commit | 778eeb1b199b85bec79b49ac483b013e270636ea (patch) | |
tree | 51a33ec4e5e81296f31fef98b89253855dc2368d /arch/mips/kernel/csrc-gic.c | |
parent | 4cb764b4541fe9eacc237b6851198a4c8497b9c4 (diff) |
MIPS: Add new GIC clocksource.
Add new clocksource that uses the counter present on the MIPS
Global Interrupt Controller.
Signed-off-by: Steven J. Hill <sjhill@mips.com>
Patchwork: http://patchwork.linux-mips.org/patch/4681/
Signed-off-by: John Crispin <blogic@openwrt.org>
Diffstat (limited to 'arch/mips/kernel/csrc-gic.c')
-rw-r--r-- | arch/mips/kernel/csrc-gic.c | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/arch/mips/kernel/csrc-gic.c b/arch/mips/kernel/csrc-gic.c new file mode 100644 index 000000000000..5dca24bce51b --- /dev/null +++ b/arch/mips/kernel/csrc-gic.c @@ -0,0 +1,49 @@ +/* + * 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/clocksource.h> +#include <linux/init.h> + +#include <asm/time.h> +#include <asm/gic.h> + +static cycle_t gic_hpt_read(struct clocksource *cs) +{ + unsigned int hi, hi2, lo; + + do { + GICREAD(GIC_REG(SHARED, GIC_SH_COUNTER_63_32), hi); + GICREAD(GIC_REG(SHARED, GIC_SH_COUNTER_31_00), lo); + GICREAD(GIC_REG(SHARED, GIC_SH_COUNTER_63_32), hi2); + } while (hi2 != hi); + + return (((cycle_t) hi) << 32) + lo; +} + +static struct clocksource gic_clocksource = { + .name = "GIC", + .read = gic_hpt_read, + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +void __init gic_clocksource_init(unsigned int frequency) +{ + unsigned int config, bits; + + /* Calculate the clocksource mask. */ + GICREAD(GIC_REG(SHARED, GIC_SH_CONFIG), config); + bits = 32 + ((config & GIC_SH_CONFIG_COUNTBITS_MSK) >> + (GIC_SH_CONFIG_COUNTBITS_SHF - 2)); + + /* Set clocksource mask. */ + gic_clocksource.mask = CLOCKSOURCE_MASK(bits); + + /* Calculate a somewhat reasonable rating value. */ + gic_clocksource.rating = 200 + frequency / 10000000; + + clocksource_register_hz(&gic_clocksource, frequency); +} |