Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:57

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RTEMSBSPsPowerPCQorIQ
0007  *
0008  * @brief QorIQ clock configuration.
0009  */
0010 
0011 /*
0012  * Copyright (C) 2011, 2017 embedded brains GmbH & Co. KG
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 COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0024  * AND 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 COPYRIGHT OWNER OR CONTRIBUTORS BE
0027  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0028  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0029  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0030  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0031  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0032  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0033  * POSSIBILITY OF SUCH DAMAGE.
0034  */
0035 
0036 #include <rtems/timecounter.h>
0037 
0038 #include <libcpu/powerpc-utility.h>
0039 
0040 #include <bsp.h>
0041 #include <bsp/fatal.h>
0042 #include <bsp/qoriq.h>
0043 #include <bsp/irq-generic.h>
0044 
0045 static struct timecounter qoriq_clock_tc;
0046 
0047 #ifdef QORIQ_IS_HYPERVISOR_GUEST
0048 
0049 #define CLOCK_DRIVER_USE_ONLY_BOOT_PROCESSOR
0050 
0051 /* This is defined in dev/clock/clockimpl.h */
0052 static rtems_isr Clock_isr(void *arg);
0053 
0054 void qoriq_decrementer_dispatch(void)
0055 {
0056   PPC_SET_SPECIAL_PURPOSE_REGISTER(BOOKE_TSR, BOOKE_TSR_DIS);
0057   Clock_isr(NULL);
0058 }
0059 
0060 static uint32_t qoriq_clock_get_timecount(struct timecounter *tc)
0061 {
0062   return ppc_alternate_time_base();
0063 }
0064 
0065 static void qoriq_clock_initialize(void)
0066 {
0067   uint64_t frequency = bsp_time_base_frequency;
0068   uint32_t us_per_tick = rtems_configuration_get_microseconds_per_tick();
0069   uint32_t interval = (uint32_t) ((frequency * us_per_tick) / 1000000);
0070 
0071   PPC_SET_SPECIAL_PURPOSE_REGISTER(BOOKE_DECAR, interval - 1);
0072   PPC_SET_SPECIAL_PURPOSE_REGISTER_BITS(
0073     BOOKE_TCR,
0074     BOOKE_TCR_DIE | BOOKE_TCR_ARE
0075   );
0076   ppc_set_decrementer_register(interval - 1);
0077 
0078   qoriq_clock_tc.tc_get_timecount = qoriq_clock_get_timecount;
0079   qoriq_clock_tc.tc_counter_mask = 0xffffffff;
0080   qoriq_clock_tc.tc_frequency = qoriq_clock_frequency;
0081   qoriq_clock_tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
0082   rtems_timecounter_install(&qoriq_clock_tc);
0083 }
0084 
0085 #else /* !QORIQ_IS_HYPERVISOR_GUEST */
0086 
0087 static volatile qoriq_pic_global_timer *const qoriq_clock =
0088   #if QORIQ_CLOCK_TIMER < 4
0089     &qoriq.pic.gta [QORIQ_CLOCK_TIMER];
0090   #else
0091     &qoriq.pic.gtb [QORIQ_CLOCK_TIMER - 4];
0092   #endif
0093 
0094 static volatile qoriq_pic_global_timer *const qoriq_timecounter =
0095   #if QORIQ_CLOCK_TIMECOUNTER < 4
0096     &qoriq.pic.gta [QORIQ_CLOCK_TIMECOUNTER];
0097   #else
0098     &qoriq.pic.gtb [QORIQ_CLOCK_TIMECOUNTER - 4];
0099   #endif
0100 
0101 #define CLOCK_INTERRUPT (QORIQ_IRQ_GT_BASE + QORIQ_CLOCK_TIMER)
0102 
0103 static rtems_interrupt_entry qoriq_clock_entry;
0104 
0105 static void qoriq_clock_handler_install(rtems_interrupt_handler handler)
0106 {
0107   rtems_status_code sc = RTEMS_SUCCESSFUL;
0108 
0109 #if defined(RTEMS_MULTIPROCESSING) && !defined(RTEMS_SMP)
0110   {
0111     Processor_mask affinity;
0112 
0113     _Processor_mask_From_index(&affinity, ppc_processor_id());
0114     bsp_interrupt_set_affinity(CLOCK_INTERRUPT, &affinity);
0115   }
0116 #endif
0117 
0118   sc = rtems_interrupt_set_priority(
0119     CLOCK_INTERRUPT,
0120     QORIQ_PIC_PRIORITY_LOWEST
0121   );
0122   if (sc != RTEMS_SUCCESSFUL) {
0123     bsp_fatal(QORIQ_FATAL_CLOCK_INTERRUPT_SET_PRIORITY);
0124   }
0125 
0126   rtems_interrupt_entry_initialize(
0127     &qoriq_clock_entry,
0128     handler,
0129     NULL,
0130     "Clock"
0131   );
0132   sc = rtems_interrupt_entry_install(
0133     CLOCK_INTERRUPT,
0134     RTEMS_INTERRUPT_UNIQUE,
0135     &qoriq_clock_entry
0136   );
0137   if (sc != RTEMS_SUCCESSFUL) {
0138     bsp_fatal(QORIQ_FATAL_CLOCK_INTERRUPT_INSTALL);
0139   }
0140 }
0141 
0142 static uint32_t qoriq_clock_get_timecount(struct timecounter *tc)
0143 {
0144   uint32_t ccr = qoriq_timecounter->ccr;
0145 
0146   return GTCCR_COUNT_GET(-ccr);
0147 }
0148 
0149 static void qoriq_clock_initialize(void)
0150 {
0151   uint32_t timer_frequency = BSP_bus_frequency / 8;
0152   uint32_t interval = (uint32_t) (((uint64_t) timer_frequency
0153     * (uint64_t) rtems_configuration_get_microseconds_per_tick()) / 1000000);
0154 
0155   qoriq_clock->bcr = GTBCR_COUNT(interval - 1);
0156 
0157   qoriq_timecounter->bcr = GTBCR_COUNT(0xffffffff);
0158 
0159   qoriq_clock_tc.tc_get_timecount = qoriq_clock_get_timecount;
0160   qoriq_clock_tc.tc_counter_mask = GTCCR_COUNT_GET(0xffffffff);
0161   qoriq_clock_tc.tc_frequency = timer_frequency;
0162   qoriq_clock_tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
0163   rtems_timecounter_install(&qoriq_clock_tc);
0164 }
0165 
0166 #define Clock_driver_support_install_isr(isr) \
0167   qoriq_clock_handler_install(isr)
0168 
0169 #define Clock_driver_support_set_interrupt_affinity(online_processors) \
0170   bsp_interrupt_set_affinity(CLOCK_INTERRUPT, online_processors)
0171 
0172 #endif /* QORIQ_IS_HYPERVISOR_GUEST */
0173 
0174 #define Clock_driver_support_initialize_hardware() \
0175   qoriq_clock_initialize()
0176 
0177 /* Include shared source clock driver code */
0178 #include "../../../shared/dev/clock/clockimpl.h"