/* * arc-timer.c -- provide API for ARC timers. * * Copyright (c) 2024 Synopsys Inc. * * The authors hereby grant permission to use, copy, modify, distribute, * and license this software and its documentation for any purpose, provided * that existing copyright notices are retained in all copies and that this * notice is included verbatim in any distributions. No written agreement, * license, or royalty fee is required for any of the authorized uses. * Modifications to this software may be copyrighted by their authors * and need not follow the licensing terms described here, provided that * the new terms are clearly indicated on the first page of each file where * they apply. * */ #define ARC_TIM_BUILD 0x75 #define ARC_TIM_BUILD_VER_MASK 0x00FF #define ARC_TIM_BUILD_TIM0_FL 0x0100 #define ARC_TIM_BUILD_TIM1_FL 0x0200 #define ARC_TIM_COUNT0 0x21 #define ARC_TIM_CONTROL0 0x22 #define ARC_TIM_LIMIT0 0x23 #define ARC_TIM_COUNT1 0x100 #define ARC_TIM_CONTROL1 0x101 #define ARC_TIM_LIMIT1 0x102 #define ARC_TIM_CONTROL_NH_FL 0x0002 /* Timer used by '_default' functions. */ const unsigned int arc_timer_default = 0; /* Check if given timer exists. */ static int _arc_timer_present (unsigned int tim) { unsigned int bcr = __builtin_arc_lr (ARC_TIM_BUILD); unsigned int ver = bcr & ARC_TIM_BUILD_VER_MASK; if (ver == 0) return 0; else if (ver == 1) return 1; else if (tim == 0) return ((bcr & ARC_TIM_BUILD_TIM0_FL) != 0); else if (tim == 1) return ((bcr & ARC_TIM_BUILD_TIM1_FL) != 0); else return 0; } /* Get raw value of a given timer. */ static unsigned int _arc_timer_read (unsigned int tim) { if (_arc_timer_present (tim)) { if (tim == 0) return __builtin_arc_lr (ARC_TIM_COUNT0); else if (tim == 1) return __builtin_arc_lr (ARC_TIM_COUNT1); } return 0; } /* * Set default values to a given timer. * Defaults: Not Halted bit is set, limit is 0xFFFFFFFF, count set to 0. */ static void _arc_timer_reset (unsigned int tim) { unsigned int ctrl, tim_control, tim_count, tim_limit; if (_arc_timer_present (tim)) { if (tim == 0) { tim_control = ARC_TIM_CONTROL0; tim_count = ARC_TIM_COUNT0; tim_limit = ARC_TIM_LIMIT0; } else if (tim == 1) { tim_control = ARC_TIM_CONTROL1; tim_count = ARC_TIM_COUNT1; tim_limit = ARC_TIM_LIMIT1; } else { return; } ctrl = __builtin_arc_lr (tim_control); /* Disable timer interrupt when programming. */ __builtin_arc_sr (0, tim_control); /* Default limit is 24-bit, increase it to 32-bit. */ __builtin_arc_sr (0xFFFFFFFF, tim_limit); /* Set NH bit to count only when processor is running. */ __builtin_arc_sr (ctrl | ARC_TIM_CONTROL_NH_FL, tim_control); __builtin_arc_sr (0, tim_count); } } /* Check if arc_timer_default exists. */ int _arc_timer_default_present (void) { return _arc_timer_present (arc_timer_default); } /* Read arc_timer_default value. */ unsigned int _arc_timer_default_read (void) { return _arc_timer_read (arc_timer_default); } /* Reset arc_timer_default. */ void _arc_timer_default_reset (void) { _arc_timer_reset (arc_timer_default); }