diff options
author | Vineet Gupta <vgupta@synopsys.com> | 2013-11-07 04:27:16 -0500 |
---|---|---|
committer | Vineet Gupta <vgupta@synopsys.com> | 2015-06-22 04:36:56 -0400 |
commit | aa93e8ef98471277cfedacd68604bb28b5a35aa7 (patch) | |
tree | 40b78e1eb7d72320e33638bb6850d90fc57c02c2 | |
parent | b3210d141f5ec32d3b29d0cf4f33d922a739602f (diff) |
ARCv2: clocksource: Introduce 64bit local RTC counter
Cc: Daniel Lezcano <daniel.lezcano@linaro.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
-rw-r--r-- | arch/arc/Kconfig | 5 | ||||
-rw-r--r-- | arch/arc/kernel/setup.c | 9 | ||||
-rw-r--r-- | arch/arc/kernel/time.c | 50 |
3 files changed, 62 insertions, 2 deletions
diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig index 974ed9058018..f09e03a0d604 100644 --- a/arch/arc/Kconfig +++ b/arch/arc/Kconfig | |||
@@ -372,6 +372,11 @@ config ARC_HAS_LL64 | |||
372 | dest operands with 2 possible source operands. | 372 | dest operands with 2 possible source operands. |
373 | default y | 373 | default y |
374 | 374 | ||
375 | config ARC_HAS_RTC | ||
376 | bool "Local 64-bit r/o cycle counter" | ||
377 | default n | ||
378 | depends on !SMP | ||
379 | |||
375 | config ARC_NUMBER_OF_INTERRUPTS | 380 | config ARC_NUMBER_OF_INTERRUPTS |
376 | int "Number of interrupts" | 381 | int "Number of interrupts" |
377 | range 8 240 | 382 | range 8 240 |
diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c index ca71cef4bafd..a3d186211ed3 100644 --- a/arch/arc/kernel/setup.c +++ b/arch/arc/kernel/setup.c | |||
@@ -200,9 +200,11 @@ static char *arc_cpu_mumbojumbo(int cpu_id, char *buf, int len) | |||
200 | (unsigned int)(arc_get_core_freq() / 1000000), | 200 | (unsigned int)(arc_get_core_freq() / 1000000), |
201 | (unsigned int)(arc_get_core_freq() / 10000) % 100); | 201 | (unsigned int)(arc_get_core_freq() / 10000) % 100); |
202 | 202 | ||
203 | n += scnprintf(buf + n, len - n, "Timers\t\t: %s%s\nISA Extn\t: ", | 203 | n += scnprintf(buf + n, len - n, "Timers\t\t: %s%s%s%s\nISA Extn\t: ", |
204 | IS_AVAIL1(cpu->timers.t0, "Timer0 "), | 204 | IS_AVAIL1(cpu->timers.t0, "Timer0 "), |
205 | IS_AVAIL1(cpu->timers.t1, "Timer1 ")); | 205 | IS_AVAIL1(cpu->timers.t1, "Timer1 "), |
206 | IS_AVAIL2(cpu->timers.rtc, "64-bit RTC ", | ||
207 | CONFIG_ARC_HAS_RTC)); | ||
206 | 208 | ||
207 | n += i = scnprintf(buf + n, len - n, "%s%s%s%s%s", | 209 | n += i = scnprintf(buf + n, len - n, "%s%s%s%s%s", |
208 | IS_AVAIL2(atomic, "atomic ", CONFIG_ARC_HAS_LLSC), | 210 | IS_AVAIL2(atomic, "atomic ", CONFIG_ARC_HAS_LLSC), |
@@ -290,6 +292,9 @@ static void arc_chk_core_config(void) | |||
290 | if (!cpu->timers.t1) | 292 | if (!cpu->timers.t1) |
291 | panic("Timer1 is not present!\n"); | 293 | panic("Timer1 is not present!\n"); |
292 | 294 | ||
295 | if (IS_ENABLED(CONFIG_ARC_HAS_RTC) && !cpu->timers.rtc) | ||
296 | panic("RTC is not present\n"); | ||
297 | |||
293 | #ifdef CONFIG_ARC_HAS_DCCM | 298 | #ifdef CONFIG_ARC_HAS_DCCM |
294 | /* | 299 | /* |
295 | * DCCM can be arbit placed in hardware. | 300 | * DCCM can be arbit placed in hardware. |
diff --git a/arch/arc/kernel/time.c b/arch/arc/kernel/time.c index 71493f75ae6b..da495478a40b 100644 --- a/arch/arc/kernel/time.c +++ b/arch/arc/kernel/time.c | |||
@@ -60,6 +60,54 @@ | |||
60 | 60 | ||
61 | /********** Clock Source Device *********/ | 61 | /********** Clock Source Device *********/ |
62 | 62 | ||
63 | #ifdef CONFIG_ARC_HAS_RTC | ||
64 | |||
65 | #define AUX_RTC_CTRL 0x103 | ||
66 | #define AUX_RTC_LOW 0x104 | ||
67 | #define AUX_RTC_HIGH 0x105 | ||
68 | |||
69 | int arc_counter_setup(void) | ||
70 | { | ||
71 | write_aux_reg(AUX_RTC_CTRL, 1); | ||
72 | |||
73 | /* Not usable in SMP */ | ||
74 | return !IS_ENABLED(CONFIG_SMP); | ||
75 | } | ||
76 | |||
77 | static cycle_t arc_counter_read(struct clocksource *cs) | ||
78 | { | ||
79 | unsigned long status; | ||
80 | union { | ||
81 | #ifdef CONFIG_CPU_BIG_ENDIAN | ||
82 | struct { u32 high, low; }; | ||
83 | #else | ||
84 | struct { u32 low, high; }; | ||
85 | #endif | ||
86 | cycle_t full; | ||
87 | } stamp; | ||
88 | |||
89 | |||
90 | __asm__ __volatile( | ||
91 | "1: \n" | ||
92 | " lr %0, [AUX_RTC_LOW] \n" | ||
93 | " lr %1, [AUX_RTC_HIGH] \n" | ||
94 | " lr %2, [AUX_RTC_CTRL] \n" | ||
95 | " bbit0.nt %2, 31, 1b \n" | ||
96 | : "=r" (stamp.low), "=r" (stamp.high), "=r" (status)); | ||
97 | |||
98 | return stamp.full; | ||
99 | } | ||
100 | |||
101 | static struct clocksource arc_counter = { | ||
102 | .name = "ARCv2 RTC", | ||
103 | .rating = 350, | ||
104 | .read = arc_counter_read, | ||
105 | .mask = CLOCKSOURCE_MASK(64), | ||
106 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | ||
107 | }; | ||
108 | |||
109 | #else /* !CONFIG_ARC_HAS_RTC */ | ||
110 | |||
63 | /* | 111 | /* |
64 | * set 32bit TIMER1 to keep counting monotonically and wraparound | 112 | * set 32bit TIMER1 to keep counting monotonically and wraparound |
65 | */ | 113 | */ |
@@ -86,6 +134,8 @@ static struct clocksource arc_counter = { | |||
86 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 134 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
87 | }; | 135 | }; |
88 | 136 | ||
137 | #endif | ||
138 | |||
89 | /********** Clock Event Device *********/ | 139 | /********** Clock Event Device *********/ |
90 | 140 | ||
91 | /* | 141 | /* |