aboutsummaryrefslogtreecommitdiff
path: root/arch/arm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm')
-rwxr-xr-xarch/arm/mach-ux500/Makefile5
-rwxr-xr-xarch/arm/mach-ux500/include/mach/prcmu-regs.h5
-rw-r--r--arch/arm/mach-ux500/include/mach/setup.h1
-rw-r--r--arch/arm/mach-ux500/timer-db8500-prcm.c64
-rwxr-xr-xarch/arm/mach-ux500/timer.c3
5 files changed, 76 insertions, 2 deletions
diff --git a/arch/arm/mach-ux500/Makefile b/arch/arm/mach-ux500/Makefile
index 18659458f7b..5ab3099c584 100755
--- a/arch/arm/mach-ux500/Makefile
+++ b/arch/arm/mach-ux500/Makefile
@@ -8,7 +8,8 @@ ifeq ($(CONFIG_CRYPTO_DEV_UX500_HASH), m)
CFLAGS_board-mop500.o += -DCONFIG_CRYPTO_DEV_UX500_HASH
endif
-obj-y := clock.o timer.o timer-rtt.o gpio.o localtimer.o
+obj-y := clock.o timer.o timer-rtt.o gpio.o \
+ localtimer.o
obj-$(CONFIG_REGULATOR) += regulator.o mop500-regulators.o
obj-$(CONFIG_ARCH_U8500) += devices.o cpu.o
obj-$(CONFIG_STM_DMA) += dma_40.o #part1 no. of dma is 0x40
@@ -16,7 +17,7 @@ obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
obj-$(CONFIG_MACH_U8500_MOP) += board-mop500.o mop500-sdi.o
obj-$(CONFIG_UX500_SOC_DB5500) += db5500-devices.o cpu-db5500.o
obj-$(CONFIG_UX500_SOC_DB8500) += db8500-devices.o hsi.o mcde.o \
- cpu-db8500.o prcmu-fw.o
+ cpu-db8500.o prcmu-fw.o timer-db8500-prcm.o
obj-$(CONFIG_FB_MCDE) += board-mop500-mcde.o
obj-$(CONFIG_MACH_U8500_SIMULATOR) += board-mop500.o mop500-sdi.o
obj-$(CONFIG_MACH_U5500_SIMULATOR) += board-u5500.o
diff --git a/arch/arm/mach-ux500/include/mach/prcmu-regs.h b/arch/arm/mach-ux500/include/mach/prcmu-regs.h
index 0972342dfb5..fadf75ed896 100755
--- a/arch/arm/mach-ux500/include/mach/prcmu-regs.h
+++ b/arch/arm/mach-ux500/include/mach/prcmu-regs.h
@@ -67,6 +67,11 @@
/* System reset register */
#define PRCM_APE_SOFTRST (_PRCMU_BASE + 0x228)
+/* PRCM Timer 5 */
+#define PRCM_TIMER_5_REF (_PRCMU_BASE + 0x45C)
+#define PRCM_TIMER_5_DOWNCOUNT (_PRCMU_BASE + 0x460)
+#define PRCM_TIMER_5_MODE (_PRCMU_BASE + 0x464)
+
/* Level shifter and clamp control registers */
#define PRCM_MMIP_LS_CLAMP_SET (_PRCMU_BASE + 0x420)
#define PRCM_MMIP_LS_CLAMP_CLR (_PRCMU_BASE + 0x424)
diff --git a/arch/arm/mach-ux500/include/mach/setup.h b/arch/arm/mach-ux500/include/mach/setup.h
index 2404563ec90..1c2ba88d523 100644
--- a/arch/arm/mach-ux500/include/mach/setup.h
+++ b/arch/arm/mach-ux500/include/mach/setup.h
@@ -31,6 +31,7 @@ extern void __init ux500_init_irq(void);
extern void __init amba_add_devices(struct amba_device *devs[], int num);
extern struct sys_timer u8500_timer;
+extern void __init db8500_prcm_timer_init(void);
#define __IO_DEV_DESC(x, sz) { \
.virtual = IO_ADDRESS(x), \
diff --git a/arch/arm/mach-ux500/timer-db8500-prcm.c b/arch/arm/mach-ux500/timer-db8500-prcm.c
new file mode 100644
index 00000000000..fadd56a50d9
--- /dev/null
+++ b/arch/arm/mach-ux500/timer-db8500-prcm.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License Terms: GNU General Public License v2
+ * Author: Sundar Iyer <sundar.iyer@stericsson.com> for ST-Ericsson
+ *
+ * DB8500-PRCM Timer
+ * The PRCM has 5 timers which are available in a always-on
+ * power domain. we use the Timer 5 for our always-on clock source.
+ */
+#include <linux/io.h>
+#include <linux/clockchips.h>
+#include <linux/clk.h>
+#include <linux/jiffies.h>
+#include <mach/setup.h>
+#include <mach/prcmu-regs.h>
+
+#define RATE_32K (32768)
+
+#define TIMER_MODE_CONTINOUS (0x1)
+#define TIMER_DOWNCOUNT_VAL (0xffffffff)
+
+/*
+ * clocksource: the prcm timer is a decrementing counters, so we negate
+ * the value being read.
+ */
+static cycle_t db8500_prcm_read_timer(void)
+{
+ u32 count = readl(PRCM_TIMER_5_DOWNCOUNT);
+ return ~count;
+}
+
+static struct clocksource db8500_prcm_clksrc = {
+ .name = "db8500-prcm-timer5",
+ .rating = 500,
+ .read = db8500_prcm_read_timer,
+ .shift = 10,
+ .mask = CLOCKSOURCE_MASK(32),
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+void __init db8500_prcm_timer_init(void)
+{
+ /*
+ * The A9 sub system expects the timer to be configured as
+ * a continous looping timer. If this timer is not configured
+ * in such a mode, then do so.
+ * Later on, when the PRCM decides to init this timer, the A9
+ * can rest assure that it need not init the timer
+ */
+ if (readl(PRCM_TIMER_5_MODE) != TIMER_MODE_CONTINOUS) {
+ writel(TIMER_MODE_CONTINOUS, PRCM_TIMER_5_MODE);
+ writel(TIMER_DOWNCOUNT_VAL, PRCM_TIMER_5_REF);
+ }
+
+ /* register the clock source */
+ db8500_prcm_clksrc.mult = clocksource_hz2mult(RATE_32K,
+ db8500_prcm_clksrc.shift);
+
+ clocksource_register(&db8500_prcm_clksrc);
+
+ return;
+}
+
diff --git a/arch/arm/mach-ux500/timer.c b/arch/arm/mach-ux500/timer.c
index b5cdd87e79f..d5f27a6fae0 100755
--- a/arch/arm/mach-ux500/timer.c
+++ b/arch/arm/mach-ux500/timer.c
@@ -177,6 +177,9 @@ static void __init u8500_timer_init(void)
/* Init the timer and register clocksource */
u8500_timer_reset();
+ /* register db8500-prcmu timer as always-on clock source */
+ db8500_prcm_timer_init();
+
u8500_clksrc.mult = clocksource_hz2mult(rate, u8500_clksrc.shift);
bits = 8*sizeof(u8500_count);