Back to home page

LXR

 
 

    


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

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RTEMSBSPsX8664AMD64
0007  *
0008  * @brief APIC timer clock implementation
0009  */
0010 
0011 /*
0012  * Copyright (c) 2018 Amaan Cheval <amaan.cheval@gmail.com>
0013  *
0014  * Redistribution and use in source and binary forms, with or without
0015  * modification, are permitted provided that the following conditions
0016  * are met:
0017  * 1. Redistributions of source code must retain the above copyright
0018  *    notice, this list of conditions and the following disclaimer.
0019  * 2. Redistributions in binary form must reproduce the above copyright
0020  *    notice, this list of conditions and the following disclaimer in the
0021  *    documentation and/or other materials provided with the distribution.
0022  *
0023  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
0024  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0025  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0026  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
0027  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
0028  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
0029  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
0030  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
0031  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
0032  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
0033  * SUCH DAMAGE.
0034  */
0035 
0036 #include <stdio.h>
0037 #include <assert.h>
0038 #include <bsp.h>
0039 #include <rtems.h>
0040 #include <apic.h>
0041 #include <clock.h>
0042 #include <rtems/score/idt.h>
0043 #include <rtems/timecounter.h>
0044 #include <rtems/score/cpu.h>
0045 #include <rtems/score/cpuimpl.h>
0046 #include <rtems/score/x86_64.h>
0047 #include <bsp/irq-generic.h>
0048 #include <rtems/score/smpimpl.h>
0049 
0050 static struct timecounter amd64_clock_tc;
0051 
0052 extern volatile uint32_t Clock_driver_ticks;
0053 extern void Clock_isr(void *param);
0054 
0055 static uint32_t amd64_clock_get_timecount(struct timecounter *tc)
0056 {
0057   return Clock_driver_ticks;
0058 }
0059 
0060 static void lapic_timer_isr(void *param)
0061 {
0062   Clock_isr(param);
0063   lapic_eoi();
0064 }
0065 
0066 #ifdef RTEMS_SMP
0067 static void smp_lapic_timer_enable(void* arg)
0068 {
0069   uint32_t* lapic_reload_value = (uint32_t*) arg;
0070   lapic_timer_enable(*lapic_reload_value);
0071 }
0072 #endif
0073 
0074 void lapic_timer_install_handler(void)
0075 {
0076   rtems_status_code sc = rtems_interrupt_handler_install(
0077     BSP_VECTOR_APIC_TIMER,
0078     "LAPIC timer",
0079     RTEMS_INTERRUPT_UNIQUE,
0080     lapic_timer_isr,
0081     NULL
0082   );
0083   assert(sc == RTEMS_SUCCESSFUL);
0084 }
0085 
0086 void amd64_clock_driver_initialize(void)
0087 {
0088   uint64_t us_per_tick = rtems_configuration_get_microseconds_per_tick();
0089   uint64_t irq_ticks_per_sec = 1000000 / us_per_tick;
0090   DBG_PRINTF(
0091     "us_per_tick = %d\nDesired frequency = %d irqs/sec\n",
0092     us_per_tick,
0093     irq_ticks_per_sec
0094   );
0095 
0096   /* Setup and initialize the Local APIC timer */
0097   uint32_t lapic_reload_value = lapic_timer_calc_ticks(irq_ticks_per_sec);
0098 #ifdef RTEMS_SMP
0099   _SMP_Broadcast_action(smp_lapic_timer_enable, &lapic_reload_value);
0100 #else
0101   lapic_timer_enable(lapic_reload_value);
0102 #endif
0103 
0104   amd64_clock_tc.tc_get_timecount = amd64_clock_get_timecount;
0105   amd64_clock_tc.tc_counter_mask = 0xffffffff;
0106   amd64_clock_tc.tc_frequency = irq_ticks_per_sec;
0107   amd64_clock_tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
0108   rtems_timecounter_install(&amd64_clock_tc);
0109 }
0110 
0111 #define Clock_driver_support_install_isr(_new) \
0112   lapic_timer_install_handler()
0113 
0114 #define Clock_driver_support_initialize_hardware() \
0115   amd64_clock_driver_initialize()
0116 
0117 #include "../../../shared/dev/clock/clockimpl.h"