From 3956b4a499ce066d04fc7e21aee244cf4f582e90 Mon Sep 17 00:00:00 2001 From: Sundar R Iyer Date: Thu, 24 Jun 2010 12:08:37 +0530 Subject: ux500: add PRCM timer as an always on clock source The PRCMU timers are available in the Periph4 or the always-on power domain, ensuring that these will be functional even when the system goes to sleep/deep sleep states. The decision to enable/disable the timers from the ARM is now decisional based on the PRCMU f/w version (dummy placeholder for now) ST-Ericsson Change ID: 256290 Signed-off-by: Sundar R Iyer Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/1987 Reviewed-by: Jonas ABERG Reviewed-by: Rickard ANDERSSON Signed-off-by: Mian Yousaf Kaukab Change-Id: Iec790b71c23c5661652decdfa299a068be50975e Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/2842 --- arch/arm/mach-ux500/Makefile | 5 ++- arch/arm/mach-ux500/include/mach/prcmu-regs.h | 5 +++ arch/arm/mach-ux500/include/mach/setup.h | 1 + arch/arm/mach-ux500/timer-db8500-prcm.c | 64 +++++++++++++++++++++++++++ arch/arm/mach-ux500/timer.c | 3 ++ 5 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 arch/arm/mach-ux500/timer-db8500-prcm.c 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 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 +#include +#include +#include +#include +#include + +#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); -- cgit v1.2.3