diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig index ef5ca5969eaf3c2bdb7573e717d7660d60f5d8e4..1b684595e25846fed3a054570b2281e7c92c8451 100644 --- a/arch/arc/Kconfig +++ b/arch/arc/Kconfig @@ -384,6 +384,11 @@ config ARC_HAS_RTC default n depends on !SMP +config ARC_HAS_GRTC + bool "SMP synchronized 64-bit cycle counter" + default y + depends on SMP + config ARC_NUMBER_OF_INTERRUPTS int "Number of interrupts" range 8 240 diff --git a/arch/arc/include/asm/mcip.h b/arch/arc/include/asm/mcip.h index 31f9bac77a279d1e00a47e7cd3f8bc7cc2520709..52c11f0bb0e5b5afbeacda75ef9c014032de4fb4 100644 --- a/arch/arc/include/asm/mcip.h +++ b/arch/arc/include/asm/mcip.h @@ -39,6 +39,9 @@ struct mcip_cmd { #define CMD_DEBUG_SET_MASK 0x34 #define CMD_DEBUG_SET_SELECT 0x36 +#define CMD_GRTC_READ_LO 0x42 +#define CMD_GRTC_READ_HI 0x43 + #define CMD_IDU_ENABLE 0x71 #define CMD_IDU_DISABLE 0x72 #define CMD_IDU_SET_MODE 0x74 diff --git a/arch/arc/kernel/mcip.c b/arch/arc/kernel/mcip.c index 35921c3ab3948190bbf4b7b82bf617a3080e5c44..ad7e90b97f6ecab5e793a0cc56721e3a6ae37dc4 100644 --- a/arch/arc/kernel/mcip.c +++ b/arch/arc/kernel/mcip.c @@ -154,4 +154,7 @@ void mcip_init_early_smp(void) __mcip_cmd_data(CMD_DEBUG_SET_SELECT, 0, 0xf); __mcip_cmd_data(CMD_DEBUG_SET_MASK, 0xf, 0xf); } + + if (IS_ENABLED(CONFIG_ARC_HAS_GRTC) && !mp.grtc) + panic("kernel trying to use non-existent GRTC\n"); } diff --git a/arch/arc/kernel/time.c b/arch/arc/kernel/time.c index da495478a40b6d4f204c4043c058e75178d004f6..3364d2bbc515471bba6478b8b34a417251ffde56 100644 --- a/arch/arc/kernel/time.c +++ b/arch/arc/kernel/time.c @@ -45,6 +45,8 @@ #include #include +#include + /* Timer related Aux registers */ #define ARC_REG_TIMER0_LIMIT 0x23 /* timer 0 limit */ #define ARC_REG_TIMER0_CTRL 0x22 /* timer 0 control */ @@ -60,6 +62,48 @@ /********** Clock Source Device *********/ +#ifdef CONFIG_ARC_HAS_GRTC + +static int arc_counter_setup(void) +{ + return 1; +} + +static cycle_t arc_counter_read(struct clocksource *cs) +{ + unsigned long flags; + union { +#ifdef CONFIG_CPU_BIG_ENDIAN + struct { u32 h, l; }; +#else + struct { u32 l, h; }; +#endif + cycle_t full; + } stamp; + + local_irq_save(flags); + + __mcip_cmd(CMD_GRTC_READ_LO, 0); + stamp.l = read_aux_reg(ARC_REG_MCIP_READBACK); + + __mcip_cmd(CMD_GRTC_READ_HI, 0); + stamp.h = read_aux_reg(ARC_REG_MCIP_READBACK); + + local_irq_restore(flags); + + return stamp.full; +} + +static struct clocksource arc_counter = { + .name = "ARConnect GRTC", + .rating = 400, + .read = arc_counter_read, + .mask = CLOCKSOURCE_MASK(64), + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +#else + #ifdef CONFIG_ARC_HAS_RTC #define AUX_RTC_CTRL 0x103 @@ -134,6 +178,7 @@ static struct clocksource arc_counter = { .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; +#endif #endif /********** Clock Event Device *********/