diff options
Diffstat (limited to 'arch/microblaze/kernel/timer.c')
| -rw-r--r-- | arch/microblaze/kernel/timer.c | 24 |
1 files changed, 21 insertions, 3 deletions
diff --git a/arch/microblaze/kernel/timer.c b/arch/microblaze/kernel/timer.c index ed61b2f17719..b1380ae93ae1 100644 --- a/arch/microblaze/kernel/timer.c +++ b/arch/microblaze/kernel/timer.c | |||
| @@ -28,6 +28,7 @@ | |||
| 28 | #include <asm/prom.h> | 28 | #include <asm/prom.h> |
| 29 | #include <asm/irq.h> | 29 | #include <asm/irq.h> |
| 30 | #include <asm/system.h> | 30 | #include <asm/system.h> |
| 31 | #include <linux/cnt32_to_63.h> | ||
| 31 | 32 | ||
| 32 | #ifdef CONFIG_SELFMOD_TIMER | 33 | #ifdef CONFIG_SELFMOD_TIMER |
| 33 | #include <asm/selfmod.h> | 34 | #include <asm/selfmod.h> |
| @@ -135,7 +136,7 @@ static void microblaze_timer_set_mode(enum clock_event_mode mode, | |||
| 135 | static struct clock_event_device clockevent_microblaze_timer = { | 136 | static struct clock_event_device clockevent_microblaze_timer = { |
| 136 | .name = "microblaze_clockevent", | 137 | .name = "microblaze_clockevent", |
| 137 | .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC, | 138 | .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC, |
| 138 | .shift = 24, | 139 | .shift = 8, |
| 139 | .rating = 300, | 140 | .rating = 300, |
| 140 | .set_next_event = microblaze_timer_set_next_event, | 141 | .set_next_event = microblaze_timer_set_next_event, |
| 141 | .set_mode = microblaze_timer_set_mode, | 142 | .set_mode = microblaze_timer_set_mode, |
| @@ -195,7 +196,7 @@ static cycle_t microblaze_cc_read(const struct cyclecounter *cc) | |||
| 195 | static struct cyclecounter microblaze_cc = { | 196 | static struct cyclecounter microblaze_cc = { |
| 196 | .read = microblaze_cc_read, | 197 | .read = microblaze_cc_read, |
| 197 | .mask = CLOCKSOURCE_MASK(32), | 198 | .mask = CLOCKSOURCE_MASK(32), |
| 198 | .shift = 24, | 199 | .shift = 8, |
| 199 | }; | 200 | }; |
| 200 | 201 | ||
| 201 | int __init init_microblaze_timecounter(void) | 202 | int __init init_microblaze_timecounter(void) |
| @@ -213,7 +214,7 @@ static struct clocksource clocksource_microblaze = { | |||
| 213 | .rating = 300, | 214 | .rating = 300, |
| 214 | .read = microblaze_read, | 215 | .read = microblaze_read, |
| 215 | .mask = CLOCKSOURCE_MASK(32), | 216 | .mask = CLOCKSOURCE_MASK(32), |
| 216 | .shift = 24, /* I can shift it */ | 217 | .shift = 8, /* I can shift it */ |
| 217 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 218 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
| 218 | }; | 219 | }; |
| 219 | 220 | ||
| @@ -235,6 +236,12 @@ static int __init microblaze_clocksource_init(void) | |||
| 235 | return 0; | 236 | return 0; |
| 236 | } | 237 | } |
| 237 | 238 | ||
| 239 | /* | ||
| 240 | * We have to protect accesses before timer initialization | ||
| 241 | * and return 0 for sched_clock function below. | ||
| 242 | */ | ||
| 243 | static int timer_initialized; | ||
| 244 | |||
| 238 | void __init time_init(void) | 245 | void __init time_init(void) |
| 239 | { | 246 | { |
| 240 | u32 irq, i = 0; | 247 | u32 irq, i = 0; |
| @@ -289,4 +296,15 @@ void __init time_init(void) | |||
| 289 | #endif | 296 | #endif |
| 290 | microblaze_clocksource_init(); | 297 | microblaze_clocksource_init(); |
| 291 | microblaze_clockevent_init(); | 298 | microblaze_clockevent_init(); |
| 299 | timer_initialized = 1; | ||
| 300 | } | ||
| 301 | |||
| 302 | unsigned long long notrace sched_clock(void) | ||
| 303 | { | ||
| 304 | if (timer_initialized) { | ||
| 305 | struct clocksource *cs = &clocksource_microblaze; | ||
| 306 | cycle_t cyc = cnt32_to_63(cs->read(NULL)); | ||
| 307 | return clocksource_cyc2ns(cyc, cs->mult, cs->shift); | ||
| 308 | } | ||
| 309 | return 0; | ||
| 292 | } | 310 | } |
