Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  *
0004  * Copyright (C) 2015 Numascale AS. All rights reserved.
0005  */
0006 
0007 #include <linux/clockchips.h>
0008 
0009 #include <asm/irq.h>
0010 #include <asm/numachip/numachip.h>
0011 #include <asm/numachip/numachip_csr.h>
0012 
0013 static DEFINE_PER_CPU(struct clock_event_device, numachip2_ced);
0014 
0015 static cycles_t numachip2_timer_read(struct clocksource *cs)
0016 {
0017     return numachip2_read64_lcsr(NUMACHIP2_TIMER_NOW);
0018 }
0019 
0020 static struct clocksource numachip2_clocksource = {
0021     .name            = "numachip2",
0022     .rating          = 295,
0023     .read            = numachip2_timer_read,
0024     .mask            = CLOCKSOURCE_MASK(64),
0025     .flags           = CLOCK_SOURCE_IS_CONTINUOUS,
0026     .mult            = 1,
0027     .shift           = 0,
0028 };
0029 
0030 static int numachip2_set_next_event(unsigned long delta, struct clock_event_device *ced)
0031 {
0032     numachip2_write64_lcsr(NUMACHIP2_TIMER_DEADLINE + numachip2_timer(),
0033         delta);
0034     return 0;
0035 }
0036 
0037 static const struct clock_event_device numachip2_clockevent __initconst = {
0038     .name            = "numachip2",
0039     .rating          = 400,
0040     .set_next_event  = numachip2_set_next_event,
0041     .features        = CLOCK_EVT_FEAT_ONESHOT,
0042     .mult            = 1,
0043     .shift           = 0,
0044     .min_delta_ns    = 1250,
0045     .min_delta_ticks = 1250,
0046     .max_delta_ns    = LONG_MAX,
0047     .max_delta_ticks = LONG_MAX,
0048 };
0049 
0050 static void numachip_timer_interrupt(void)
0051 {
0052     struct clock_event_device *ced = this_cpu_ptr(&numachip2_ced);
0053 
0054     ced->event_handler(ced);
0055 }
0056 
0057 static __init void numachip_timer_each(struct work_struct *work)
0058 {
0059     unsigned local_apicid = __this_cpu_read(x86_cpu_to_apicid) & 0xff;
0060     struct clock_event_device *ced = this_cpu_ptr(&numachip2_ced);
0061 
0062     /* Setup IPI vector to local core and relative timing mode */
0063     numachip2_write64_lcsr(NUMACHIP2_TIMER_INT + numachip2_timer(),
0064         (3 << 22) | (X86_PLATFORM_IPI_VECTOR << 14) |
0065         (local_apicid << 6));
0066 
0067     *ced = numachip2_clockevent;
0068     ced->cpumask = cpumask_of(smp_processor_id());
0069     clockevents_register_device(ced);
0070 }
0071 
0072 static int __init numachip_timer_init(void)
0073 {
0074     if (numachip_system != 2)
0075         return -ENODEV;
0076 
0077     /* Reset timer */
0078     numachip2_write64_lcsr(NUMACHIP2_TIMER_RESET, 0);
0079     clocksource_register_hz(&numachip2_clocksource, NSEC_PER_SEC);
0080 
0081     /* Setup per-cpu clockevents */
0082     x86_platform_ipi_callback = numachip_timer_interrupt;
0083     schedule_on_each_cpu(&numachip_timer_each);
0084 
0085     return 0;
0086 }
0087 
0088 arch_initcall(numachip_timer_init);