Blame view
drivers/clocksource/clksrc-dbx500-prcmu.c
2.42 KB
489bccea6 clocksource: add ... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
/* * Copyright (C) ST-Ericsson SA 2011 * * License Terms: GNU General Public License v2 * Author: Mattias Wallin <mattias.wallin@stericsson.com> for ST-Ericsson * Author: Sundar Iyer for ST-Ericsson * sched_clock implementation is based on: * plat-nomadik/timer.c Linus Walleij <linus.walleij@stericsson.com> * * DBx500-PRCMU Timer * The PRCMU has 5 timers which are available in a always-on * power domain. We use the Timer 4 for our always-on clock * source on DB8500 and Timer 3 on DB5500. */ #include <linux/clockchips.h> #include <linux/clksrc-dbx500-prcmu.h> #include <asm/sched_clock.h> #include <mach/setup.h> #include <mach/hardware.h> #define RATE_32K 32768 #define TIMER_MODE_CONTINOUS 0x1 #define TIMER_DOWNCOUNT_VAL 0xffffffff #define PRCMU_TIMER_REF 0 #define PRCMU_TIMER_DOWNCOUNT 0x4 #define PRCMU_TIMER_MODE 0x8 #define SCHED_CLOCK_MIN_WRAP 131072 /* 2^32 / 32768 */ |
b1e3be064 clocksource: fixu... |
33 |
static void __iomem *clksrc_dbx500_timer_base; |
489bccea6 clocksource: add ... |
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
static cycle_t clksrc_dbx500_prcmu_read(struct clocksource *cs) { u32 count, count2; do { count = readl(clksrc_dbx500_timer_base + PRCMU_TIMER_DOWNCOUNT); count2 = readl(clksrc_dbx500_timer_base + PRCMU_TIMER_DOWNCOUNT); } while (count2 != count); /* Negate because the timer is a decrementing counter */ return ~count; } static struct clocksource clocksource_dbx500_prcmu = { .name = "dbx500-prcmu-timer", .rating = 300, .read = clksrc_dbx500_prcmu_read, |
489bccea6 clocksource: add ... |
54 55 56 57 58 |
.mask = CLOCKSOURCE_MASK(32), .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; #ifdef CONFIG_CLKSRC_DBX500_PRCMU_SCHED_CLOCK |
489bccea6 clocksource: add ... |
59 |
|
cfef0320e ARM: 7261/1: cloc... |
60 |
static u32 notrace dbx500_prcmu_sched_clock_read(void) |
489bccea6 clocksource: add ... |
61 |
{ |
489bccea6 clocksource: add ... |
62 63 |
if (unlikely(!clksrc_dbx500_timer_base)) return 0; |
cfef0320e ARM: 7261/1: cloc... |
64 |
return clksrc_dbx500_prcmu_read(&clocksource_dbx500_prcmu); |
489bccea6 clocksource: add ... |
65 |
} |
489bccea6 clocksource: add ... |
66 |
#endif |
b1e3be064 clocksource: fixu... |
67 |
void __init clksrc_dbx500_prcmu_init(void __iomem *base) |
489bccea6 clocksource: add ... |
68 |
{ |
b1e3be064 clocksource: fixu... |
69 |
clksrc_dbx500_timer_base = base; |
489bccea6 clocksource: add ... |
70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
/* * The A9 sub system expects the timer to be configured as * a continous looping timer. * The PRCMU should configure it but if it for some reason * don't we do it here. */ if (readl(clksrc_dbx500_timer_base + PRCMU_TIMER_MODE) != TIMER_MODE_CONTINOUS) { writel(TIMER_MODE_CONTINOUS, clksrc_dbx500_timer_base + PRCMU_TIMER_MODE); writel(TIMER_DOWNCOUNT_VAL, clksrc_dbx500_timer_base + PRCMU_TIMER_REF); } #ifdef CONFIG_CLKSRC_DBX500_PRCMU_SCHED_CLOCK |
cfef0320e ARM: 7261/1: cloc... |
84 |
setup_sched_clock(dbx500_prcmu_sched_clock_read, |
489bccea6 clocksource: add ... |
85 86 |
32, RATE_32K); #endif |
13f0f030f clocksource: dbx5... |
87 |
clocksource_register_hz(&clocksource_dbx500_prcmu, RATE_32K); |
489bccea6 clocksource: add ... |
88 |
} |