Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:00

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*
0004  *  Clock Tick Device Driver
0005  *
0006  *  This routine initializes GRLIB gptimer 1 which used for the clock tick.
0007  *
0008  *  The tick frequency is directly programmed to the configured number of
0009  *  microseconds per tick.
0010  *
0011  *  COPYRIGHT (c) 1989-2006.
0012  *  On-Line Applications Research Corporation (OAR).
0013  *
0014  *  Modified for GRLIB BSP.
0015  *  COPYRIGHT (c) 2004.
0016  *  Gaisler Research.
0017  *
0018  *  Copyright (C) 2014, 2018 embedded brains GmbH & Co. KG
0019  *
0020  * Redistribution and use in source and binary forms, with or without
0021  * modification, are permitted provided that the following conditions
0022  * are met:
0023  * 1. Redistributions of source code must retain the above copyright
0024  *    notice, this list of conditions and the following disclaimer.
0025  * 2. Redistributions in binary form must reproduce the above copyright
0026  *    notice, this list of conditions and the following disclaimer in the
0027  *    documentation and/or other materials provided with the distribution.
0028  *
0029  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0030  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0031  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0032  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0033  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0034  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0035  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0036  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0037  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0038  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0039  * POSSIBILITY OF SUCH DAMAGE.
0040  */
0041 
0042 #include <bsp.h>
0043 #include <amba.h>
0044 #include <bsp/irq-generic.h>
0045 #include <bspopts.h>
0046 #include <bsp/fatal.h>
0047 #include <rtems/rtems/intr.h>
0048 #include <grlib/ambapp.h>
0049 #include <rtems/score/profiling.h>
0050 #include <rtems/timecounter.h>
0051 #include <rtems/score/cpuimpl.h>
0052 #include <rtems/score/riscv-utility.h>
0053 
0054 volatile uint32_t _RISCV_Counter_register;
0055 
0056 /* The GRLIB BSP Timer driver can rely on the Driver Manager if the
0057  * DrvMgr is initialized during startup. Otherwise the classic driver
0058  * must be used.
0059  *
0060  * The DrvMgr Clock driver is located in the shared/timer directory
0061  */
0062 #ifndef RTEMS_DRVMGR_STARTUP
0063 
0064 /* GRLIB Timer system interrupt number */
0065 static int clkirq;
0066 
0067 static void (*grlib_tc_tick)(void);
0068 
0069 static struct timecounter grlib_tc;
0070 
0071 #ifdef RTEMS_PROFILING
0072 #define IRQMP_TIMESTAMP_S1_S2 ((1U << 25) | (1U << 26))
0073 
0074 static void grlib_tc_tick_irqmp_timestamp(void)
0075 {
0076   volatile struct irqmp_timestamp_regs *irqmp_ts =
0077     &GRLIB_IrqCtrl_Regs->timestamp[0];
0078   unsigned int first = irqmp_ts->assertion;
0079   unsigned int second = irqmp_ts->counter;
0080 
0081   irqmp_ts->control |= IRQMP_TIMESTAMP_S1_S2;
0082 
0083   _Profiling_Update_max_interrupt_delay(_Per_CPU_Get(), second - first);
0084 
0085   rtems_timecounter_tick();
0086 }
0087 #endif
0088 
0089 static void grlib_tc_tick_irqmp_timestamp_init(void)
0090 {
0091 #ifdef RTEMS_PROFILING
0092   /*
0093    * Ignore the first clock interrupt, since it contains the sequential system
0094    * initialization time.  Do the timestamp initialization on the fly.
0095    */
0096 
0097 #ifdef RTEMS_SMP
0098   static Atomic_Uint counter = ATOMIC_INITIALIZER_UINT(0);
0099 
0100   bool done =
0101     _Atomic_Fetch_add_uint(&counter, 1, ATOMIC_ORDER_RELAXED)
0102       == rtems_scheduler_get_processor_maximum() - 1;
0103 #else
0104   bool done = true;
0105 #endif
0106 
0107   volatile struct irqmp_timestamp_regs *irqmp_ts =
0108     &GRLIB_IrqCtrl_Regs->timestamp[0];
0109   unsigned int ks = 1U << 5;
0110 
0111   irqmp_ts->control = ks | IRQMP_TIMESTAMP_S1_S2 | (unsigned int) clkirq;
0112 
0113   if (done) {
0114     grlib_tc_tick = grlib_tc_tick_irqmp_timestamp;
0115   }
0116 #endif
0117 
0118   rtems_timecounter_tick();
0119 }
0120 
0121 static void grlib_tc_do_tick(void)
0122 {
0123   (*grlib_tc_tick)();
0124 }
0125 
0126 #define Adjust_clkirq_for_node() do { clkirq += GRLIB_CLOCK_INDEX; } while(0)
0127 
0128 #define Clock_driver_support_find_timer() \
0129   do { \
0130     /* Assume timer found during BSP initialization */ \
0131     if (GRLIB_Timer_Regs) { \
0132       clkirq = (GRLIB_Timer_Regs->cfg & 0xf8) >> 3; \
0133       \
0134       Adjust_clkirq_for_node(); \
0135     } \
0136   } while (0)
0137 
0138 #define Clock_driver_support_install_isr( _new ) \
0139   bsp_clock_handler_install(_new)
0140 
0141 static void bsp_clock_handler_install(rtems_isr *new)
0142 {
0143   rtems_status_code sc;
0144 
0145   sc = rtems_interrupt_handler_install(
0146     clkirq,
0147     "Clock",
0148     RTEMS_INTERRUPT_UNIQUE,
0149     new,
0150     NULL
0151   );
0152   if (sc != RTEMS_SUCCESSFUL) {
0153     rtems_fatal(RTEMS_FATAL_SOURCE_BSP, LEON3_FATAL_CLOCK_INITIALIZATION);
0154   }
0155 }
0156 
0157 #define Clock_driver_support_set_interrupt_affinity(online_processors) \
0158   bsp_interrupt_set_affinity(clkirq, online_processors)
0159 
0160 uint32_t _CPU_Counter_frequency( void )
0161 {
0162   return grlib_up_counter_frequency();
0163 }
0164 
0165 
0166 static uint32_t _RISCV_Get_timecount_csr(struct timecounter *tc)
0167 {
0168   return read_csr(time);
0169 }
0170 
0171 static void grlib_clock_initialize(void)
0172 {
0173   volatile struct gptimer_regs *gpt;
0174   struct timecounter *tc;
0175 
0176   gpt = GRLIB_Timer_Regs;
0177   tc = &grlib_tc;
0178 
0179   gpt->timer[GRLIB_CLOCK_INDEX].reload =
0180     rtems_configuration_get_microseconds_per_tick() - 1;
0181   gpt->timer[GRLIB_CLOCK_INDEX].ctrl =
0182     GPTIMER_TIMER_CTRL_EN | GPTIMER_TIMER_CTRL_RS |
0183       GPTIMER_TIMER_CTRL_LD | GPTIMER_TIMER_CTRL_IE;
0184 
0185     /* Use the RISCV time register as up-counter */
0186   tc->tc_get_timecount = _RISCV_Get_timecount_csr;
0187   tc->tc_frequency = grlib_up_counter_frequency();
0188 
0189 #ifdef RTEMS_PROFILING
0190   volatile struct irqmp_timestamp_regs *irqmp_ts =
0191     &GRLIB_IrqCtrl_Regs->timestamp[0];
0192 
0193     if (!irqmp_has_timestamp(irqmp_ts)) {
0194       bsp_fatal(GRLIB_FATAL_CLOCK_NO_IRQMP_TIMESTAMP_SUPPORT);
0195     }
0196 #endif
0197 
0198   grlib_tc_tick = grlib_tc_tick_irqmp_timestamp_init;
0199 
0200   tc->tc_counter_mask = 0xffffffff;
0201   tc->tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
0202   rtems_timecounter_install(tc);
0203 }
0204 
0205 CPU_Counter_ticks _CPU_Counter_read( void )
0206 {
0207   unsigned long timec;
0208 
0209   __asm__ volatile (
0210     ".option push\n"
0211     ".option arch, +zicsr\n"
0212     "csrr %0, time\n"
0213     ".option pop" :
0214     "=&r" ( timec )
0215   );
0216 
0217   return timec;
0218 }
0219 
0220 #define Clock_driver_support_initialize_hardware() \
0221   grlib_clock_initialize()
0222 
0223 #define Clock_driver_timecounter_tick(arg) grlib_tc_do_tick()
0224 
0225 #include "../../../shared/dev/clock/clockimpl.h"
0226 
0227 #endif