summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRabin Vincent <rabin.vincent@stericsson.com>2011-09-27 11:04:33 +0530
committerRabin VINCENT <rabin.vincent@stericsson.com>2011-10-28 05:03:33 +0200
commitc03e09ea5245e207b581a4b44016f0e989e56e33 (patch)
treed39e7766d763ea40d11aec1cd4cb3dbd07e93d18
parent83f9d2918ef0c8da5e0b07fc83e3da83cf3f7cd8 (diff)
u5500: add MTIMER clocksource
ST-Ericsson ID: 368260 ST-Ericsson Linux next: NA ST-Ericsson FOSS-OUT ID: Trivial Depends-On: I5307cb7f58fdf890896d641a8e4f49098a90b68e Change-Id: I9ef4ff1c63f6ec9293ece4013f13cf3caa707d9d Signed-off-by: Rabin Vincent <rabin.vincent@stericsson.com> Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/34307 Reviewed-by: QATOOLS Reviewed-by: QABUILD
-rw-r--r--arch/arm/mach-ux500/cpu-db5500.c1
-rw-r--r--arch/arm/mach-ux500/include/mach/db5500-regs.h1
-rw-r--r--arch/arm/mach-ux500/timer.c11
-rw-r--r--drivers/clocksource/Kconfig21
-rw-r--r--drivers/clocksource/Makefile1
-rw-r--r--drivers/clocksource/db5500-mtimer.c52
-rw-r--r--include/linux/clksrc-db5500-mtimer.h17
7 files changed, 100 insertions, 4 deletions
diff --git a/arch/arm/mach-ux500/cpu-db5500.c b/arch/arm/mach-ux500/cpu-db5500.c
index 9518c6db7f7..ea4fbbb1fc6 100644
--- a/arch/arm/mach-ux500/cpu-db5500.c
+++ b/arch/arm/mach-ux500/cpu-db5500.c
@@ -41,6 +41,7 @@ static struct map_desc u5500_io_desc[] __initdata = {
__IO_DEV_DESC(U5500_MTU1_BASE, SZ_4K),
__IO_DEV_DESC(U5500_SCU_BASE, SZ_4K),
__IO_DEV_DESC(U5500_RTC_BASE, SZ_4K),
+ __IO_DEV_DESC(U5500_MTIMER_BASE, SZ_4K),
__IO_DEV_DESC(U5500_BACKUPRAM0_BASE, SZ_8K),
__MEM_DEV_DESC(U5500_BOOT_ROM_BASE, SZ_1M),
diff --git a/arch/arm/mach-ux500/include/mach/db5500-regs.h b/arch/arm/mach-ux500/include/mach/db5500-regs.h
index 870c3ff574c..f853c20587a 100644
--- a/arch/arm/mach-ux500/include/mach/db5500-regs.h
+++ b/arch/arm/mach-ux500/include/mach/db5500-regs.h
@@ -66,6 +66,7 @@
#define U5500_PRCMU_TIMER_4_BASE (U5500_PER4_BASE + 0x07450)
#define U5500_MSP1_BASE (U5500_PER4_BASE + 0x9000)
#define U5500_GPIO2_BASE (U5500_PER4_BASE + 0xA000)
+#define U5500_MTIMER_BASE (U5500_PER4_BASE + 0xC000)
#define U5500_CDETECT_BASE (U5500_PER4_BASE + 0xF000)
#define U5500_PRCMU_TCDM_BASE (U5500_PER4_BASE + 0x18000)
#define U5500_PRCMU_TCPM_BASE (U5500_PER4_BASE + 0x10000)
diff --git a/arch/arm/mach-ux500/timer.c b/arch/arm/mach-ux500/timer.c
index c395f5c8992..df1945b1991 100644
--- a/arch/arm/mach-ux500/timer.c
+++ b/arch/arm/mach-ux500/timer.c
@@ -7,6 +7,7 @@
#include <linux/io.h>
#include <linux/errno.h>
#include <linux/clksrc-dbx500-prcmu.h>
+#include <linux/clksrc-db5500-mtimer.h>
#include <asm/localtimer.h>
@@ -67,12 +68,18 @@ static void __init ux500_timer_init(void)
* depending on delay which is not yet calibrated. RTC-RTT is in the
* always-on powerdomain and is used as clockevent instead of twd when
* sleeping.
- * The PRCMU timer 4(3 for DB5500) register a clocksource and
- * sched_clock with higher rating then MTU since is always-on.
*
+ * The PRCMU timer 4 (3 for DB5500) registers a clocksource and
+ * sched_clock with higher rating than the MTU since it is
+ * always-on.
+ *
+ * On DB5500, the MTIMER is the best clocksource since, unlike the
+ * PRCMU timer, it doesn't occasionally go backwards.
*/
nmdk_timer_init();
+ if (cpu_is_u5500())
+ db5500_mtimer_init(__io_address(U5500_MTIMER_BASE));
clksrc_dbx500_prcmu_init(prcmu_timer_base);
#ifdef CONFIG_UX500_CONTEXT
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 206f35f7d8c..75935af43f2 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -7,13 +7,30 @@ config CLKSRC_MMIO
config CLKSRC_DBX500_PRCMU
bool "Clocksource PRCMU Timer"
depends on UX500_SOC_DB5500 || UX500_SOC_DB8500
- default y
+ default y if UX500_SOC_DB8500
help
Use the always on PRCMU Timer as clocksource
config CLKSRC_DBX500_PRCMU_SCHED_CLOCK
bool "Clocksource PRCMU Timer sched_clock"
- depends on (CLKSRC_DBX500_PRCMU && !NOMADIK_MTU_SCHED_CLOCK)
+ depends on (CLKSRC_DBX500_PRCMU && !NOMADIK_MTU_SCHED_CLOCK && \
+ !CLKSRC_DB5500_MTIMER_SCHED_CLOCK)
+ select HAVE_SCHED_CLOCK
+ default y
+ help
+ Use the always on PRCMU Timer as sched_clock
+
+config CLKSRC_DB5500_MTIMER
+ bool "Clocksource MTIMER"
+ depends on UX500_SOC_DB5500
+ default y
+ help
+ Use the always on MTIMER as clocksource
+
+config CLKSRC_DB5500_MTIMER_SCHED_CLOCK
+ bool "Clocksource MTIMER sched_clock"
+ depends on (CLKSRC_DB5500_MTIMER && !NOMADIK_MTU_SCHED_CLOCK && \
+ !CLKSRC_DBX500_PRCMU_SCHED_CLOCK)
select HAVE_SCHED_CLOCK
default y
help
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 285e9a3a61f..027e71d6d05 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -9,3 +9,4 @@ obj-$(CONFIG_SH_TIMER_TMU) += sh_tmu.o
obj-$(CONFIG_CLKSRC_I8253) += i8253.o
obj-$(CONFIG_CLKSRC_MMIO) += mmio.o
obj-$(CONFIG_CLKSRC_DBX500_PRCMU) += clksrc-dbx500-prcmu.o
+obj-$(CONFIG_CLKSRC_DB5500_MTIMER) += db5500-mtimer.o
diff --git a/drivers/clocksource/db5500-mtimer.c b/drivers/clocksource/db5500-mtimer.c
new file mode 100644
index 00000000000..641279707a8
--- /dev/null
+++ b/drivers/clocksource/db5500-mtimer.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * License Terms: GNU General Public License v2
+ */
+
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/clockchips.h>
+#include <linux/clksrc-db5500-mtimer.h>
+
+#include <asm/sched_clock.h>
+
+#define MTIMER_PRIMARY_COUNTER 0x18
+
+static void __iomem *db5500_mtimer_base;
+
+#ifdef CONFIG_CLKSRC_DB5500_MTIMER_SCHED_CLOCK
+static DEFINE_CLOCK_DATA(cd);
+
+unsigned long long notrace sched_clock(void)
+{
+ u32 cyc;
+
+ if (unlikely(!db5500_mtimer_base))
+ return 0;
+
+ cyc = readl_relaxed(db5500_mtimer_base + MTIMER_PRIMARY_COUNTER);
+
+ return cyc_to_sched_clock(&cd, cyc, (u32)~0);
+}
+
+static void notrace db5500_mtimer_update_sched_clock(void)
+{
+ u32 cyc = readl_relaxed(db5500_mtimer_base + MTIMER_PRIMARY_COUNTER);
+ update_sched_clock(&cd, cyc, (u32)~0);
+}
+#endif
+
+void __init db5500_mtimer_init(void __iomem *base)
+{
+ db5500_mtimer_base = base;
+
+ clocksource_mmio_init(base + MTIMER_PRIMARY_COUNTER, "mtimer", 32768,
+ 400, 32, clocksource_mmio_readl_up);
+
+#ifdef CONFIG_CLKSRC_DB5500_MTIMER_SCHED_CLOCK
+ init_sched_clock(&cd, db5500_mtimer_update_sched_clock,
+ 32, 32768);
+#endif
+}
diff --git a/include/linux/clksrc-db5500-mtimer.h b/include/linux/clksrc-db5500-mtimer.h
new file mode 100644
index 00000000000..3112c7f2709
--- /dev/null
+++ b/include/linux/clksrc-db5500-mtimer.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * License Terms: GNU General Public License v2
+ */
+#ifndef __CLKSRC_DB5500_MTIMER_H
+#define __CLKSRC_DB5500_MTIMER_H
+
+#include <linux/io.h>
+
+#ifdef CONFIG_CLKSRC_DB5500_MTIMER
+void db5500_mtimer_init(void __iomem *base);
+#else
+static inline void db5500_mtimer_init(void __iomem *base) {}
+#endif
+
+#endif