| 1 | |
| 2 | |
| 3 | *
|
| 4 | * Copyright (C) 2015 Numascale AS. All rights reserved.
|
| 5 |
|
| 6 |
|
| 7 | #include <linux/clockchips.h>
|
| 8 |
|
| 9 | #include <asm/irq.h>
|
| 10 | #include <asm/numachip/numachip.h>
|
| 11 | #include <asm/numachip/numachip_csr.h>
|
| 12 |
|
| 13 | static DEFINE_PER_CPU(struct clock_event_device, numachip2_ced);
|
| 14 |
|
| 15 | static cycles_t numachip2_timer_read(struct clocksource *cs)
|
| 16 | {
|
| 17 | return numachip2_read64_lcsr(NUMACHIP2_TIMER_NOW);
|
| 18 | }
|
| 19 |
|
| 20 | static struct clocksource numachip2_clocksource = {
|
| 21 | .name = "numachip2",
|
| 22 | .rating = 295,
|
| 23 | .read = numachip2_timer_read,
|
| 24 | .mask = CLOCKSOURCE_MASK(64),
|
| 25 | .flags = CLOCK_SOURCE_IS_CONTINUOUS,
|
| 26 | .mult = 1,
|
| 27 | .shift = 0,
|
| 28 | };
|
| 29 |
|
| 30 | static int numachip2_set_next_event(unsigned long delta, struct clock_event_device *ced)
|
| 31 | {
|
| 32 | numachip2_write64_lcsr(NUMACHIP2_TIMER_DEADLINE + numachip2_timer(),
|
| 33 | delta);
|
| 34 | return 0;
|
| 35 | }
|
| 36 |
|
| 37 | static const struct clock_event_device numachip2_clockevent __initconst = {
|
| 38 | .name = "numachip2",
|
| 39 | .rating = 400,
|
| 40 | .set_next_event = numachip2_set_next_event,
|
| 41 | .features = CLOCK_EVT_FEAT_ONESHOT,
|
| 42 | .mult = 1,
|
| 43 | .shift = 0,
|
| 44 | .min_delta_ns = 1250,
|
| 45 | .min_delta_ticks = 1250,
|
| 46 | .max_delta_ns = LONG_MAX,
|
| 47 | .max_delta_ticks = LONG_MAX,
|
| 48 | };
|
| 49 |
|
| 50 | static void numachip_timer_interrupt(void)
|
| 51 | {
|
| 52 | struct clock_event_device *ced = this_cpu_ptr(&numachip2_ced);
|
| 53 |
|
| 54 | ced->event_handler(ced);
|
| 55 | }
|
| 56 |
|
| 57 | static __init void numachip_timer_each(struct work_struct *work)
|
| 58 | {
|
| 59 | unsigned local_apicid = __this_cpu_read(x86_cpu_to_apicid) & 0xff;
|
| 60 | struct clock_event_device *ced = this_cpu_ptr(&numachip2_ced);
|
| 61 |
|
| 62 |
|
| 63 | numachip2_write64_lcsr(NUMACHIP2_TIMER_INT + numachip2_timer(),
|
| 64 | (3 << 22) | (X86_PLATFORM_IPI_VECTOR << 14) |
|
| 65 | (local_apicid << 6));
|
| 66 |
|
| 67 | *ced = numachip2_clockevent;
|
| 68 | ced->cpumask = cpumask_of(smp_processor_id());
|
| 69 | clockevents_register_device(ced);
|
| 70 | }
|
| 71 |
|
| 72 | static int __init numachip_timer_init(void)
|
| 73 | {
|
| 74 | if (numachip_system != 2)
|
| 75 | return -ENODEV;
|
| 76 |
|
| 77 |
|
| 78 | numachip2_write64_lcsr(NUMACHIP2_TIMER_RESET, 0);
|
| 79 | clocksource_register_hz(&numachip2_clocksource, NSEC_PER_SEC);
|
| 80 |
|
| 81 |
|
| 82 | x86_platform_ipi_callback = numachip_timer_interrupt;
|
| 83 | schedule_on_each_cpu(&numachip_timer_each);
|
| 84 |
|
| 85 | return 0;
|
| 86 | }
|
| 87 |
|
| 88 | arch_initcall(numachip_timer_init);
|