2019-05-29 17:17:56 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2015-09-21 13:02:25 +03:00
/*
*
* Copyright ( C ) 2015 Numascale AS . All rights reserved .
*/
# include <linux/clockchips.h>
# include <asm/irq.h>
# include <asm/numachip/numachip.h>
# include <asm/numachip/numachip_csr.h>
2015-09-23 04:38:13 +03:00
static DEFINE_PER_CPU ( struct clock_event_device , numachip2_ced ) ;
2015-09-21 13:02:25 +03:00
static cycles_t numachip2_timer_read ( struct clocksource * cs )
{
return numachip2_read64_lcsr ( NUMACHIP2_TIMER_NOW ) ;
}
static struct clocksource numachip2_clocksource = {
. name = " numachip2 " ,
. rating = 295 ,
. read = numachip2_timer_read ,
. mask = CLOCKSOURCE_MASK ( 64 ) ,
. flags = CLOCK_SOURCE_IS_CONTINUOUS ,
. mult = 1 ,
. shift = 0 ,
} ;
static int numachip2_set_next_event ( unsigned long delta , struct clock_event_device * ced )
{
numachip2_write64_lcsr ( NUMACHIP2_TIMER_DEADLINE + numachip2_timer ( ) ,
delta ) ;
return 0 ;
}
2017-08-29 21:17:11 +03:00
static const struct clock_event_device numachip2_clockevent __initconst = {
2015-09-21 13:02:25 +03:00
. name = " numachip2 " ,
. rating = 400 ,
. set_next_event = numachip2_set_next_event ,
. features = CLOCK_EVT_FEAT_ONESHOT ,
. mult = 1 ,
. shift = 0 ,
. min_delta_ns = 1250 ,
2017-03-30 23:08:49 +03:00
. min_delta_ticks = 1250 ,
2015-09-21 13:02:25 +03:00
. max_delta_ns = LONG_MAX ,
2017-03-30 23:08:49 +03:00
. max_delta_ticks = LONG_MAX ,
2015-09-21 13:02:25 +03:00
} ;
static void numachip_timer_interrupt ( void )
{
2015-09-23 04:38:13 +03:00
struct clock_event_device * ced = this_cpu_ptr ( & numachip2_ced ) ;
2015-09-21 13:02:25 +03:00
ced - > event_handler ( ced ) ;
}
static __init void numachip_timer_each ( struct work_struct * work )
{
unsigned local_apicid = __this_cpu_read ( x86_cpu_to_apicid ) & 0xff ;
2015-09-23 04:38:13 +03:00
struct clock_event_device * ced = this_cpu_ptr ( & numachip2_ced ) ;
2015-09-21 13:02:25 +03:00
/* Setup IPI vector to local core and relative timing mode */
numachip2_write64_lcsr ( NUMACHIP2_TIMER_INT + numachip2_timer ( ) ,
( 3 < < 22 ) | ( X86_PLATFORM_IPI_VECTOR < < 14 ) |
( local_apicid < < 6 ) ) ;
* ced = numachip2_clockevent ;
ced - > cpumask = cpumask_of ( smp_processor_id ( ) ) ;
clockevents_register_device ( ced ) ;
}
static int __init numachip_timer_init ( void )
{
if ( numachip_system ! = 2 )
return - ENODEV ;
/* Reset timer */
numachip2_write64_lcsr ( NUMACHIP2_TIMER_RESET , 0 ) ;
clocksource_register_hz ( & numachip2_clocksource , NSEC_PER_SEC ) ;
/* Setup per-cpu clockevents */
x86_platform_ipi_callback = numachip_timer_interrupt ;
schedule_on_each_cpu ( & numachip_timer_each ) ;
return 0 ;
}
arch_initcall ( numachip_timer_init ) ;