File indexing completed on 2025-05-11 08:23:05
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037 #include <bsp.h>
0038 #include <bsp/fatal.h>
0039 #include <bsp/irq.h>
0040 #include <bsp/irq-generic.h>
0041 #include <bsp/arm-a9mpcore-regs.h>
0042 #include <bsp/arm-a9mpcore-clock.h>
0043 #include <rtems/timecounter.h>
0044 #include <rtems/score/smpimpl.h>
0045
0046 #define A9MPCORE_GT ((volatile a9mpcore_gt *) BSP_ARM_A9MPCORE_GT_BASE)
0047
0048 static struct timecounter a9mpcore_tc;
0049
0050 __attribute__ ((weak)) uint32_t a9mpcore_clock_periphclk(void)
0051 {
0052
0053 return BSP_ARM_A9MPCORE_PERIPHCLK;
0054 }
0055
0056 static void a9mpcore_clock_at_tick(volatile a9mpcore_gt *gt)
0057 {
0058 gt->irqst = A9MPCORE_GT_IRQST_EFLG;
0059 }
0060
0061 static rtems_interrupt_entry a9mpcore_clock_interrupt_entry;
0062
0063 static void a9mpcore_clock_handler_install(rtems_interrupt_handler handler)
0064 {
0065 rtems_status_code sc;
0066
0067 rtems_interrupt_entry_initialize(
0068 &a9mpcore_clock_interrupt_entry,
0069 handler,
0070 RTEMS_DEVOLATILE(a9mpcore_gt *, A9MPCORE_GT),
0071 "Clock"
0072 );
0073 sc = rtems_interrupt_entry_install(
0074 A9MPCORE_IRQ_GT,
0075 RTEMS_INTERRUPT_UNIQUE,
0076 &a9mpcore_clock_interrupt_entry
0077 );
0078 if (sc != RTEMS_SUCCESSFUL) {
0079 bsp_fatal(BSP_ARM_A9MPCORE_FATAL_CLOCK_IRQ_INSTALL);
0080 }
0081 }
0082
0083 static uint64_t a9mpcore_clock_get_counter(volatile a9mpcore_gt *gt)
0084 {
0085 uint32_t cl;
0086 uint32_t cu1;
0087 uint32_t cu2;
0088
0089 do {
0090 cu1 = gt->cntrupper;
0091 cl = gt->cntrlower;
0092 cu2 = gt->cntrupper;
0093 } while (cu1 != cu2);
0094
0095 return ((uint64_t) cu2 << 32) | cl;
0096 }
0097
0098 static uint32_t a9mpcore_clock_get_timecount(struct timecounter *tc)
0099 {
0100 volatile a9mpcore_gt *gt = A9MPCORE_GT;
0101
0102 return gt->cntrlower;
0103 }
0104
0105 static void a9mpcore_clock_gt_init(
0106 volatile a9mpcore_gt *gt,
0107 uint64_t cmpval,
0108 uint32_t interval
0109 )
0110 {
0111 gt->cmpvallower = (uint32_t) cmpval;
0112 gt->cmpvalupper = (uint32_t) (cmpval >> 32);
0113 gt->autoinc = interval;
0114 gt->ctrl = A9MPCORE_GT_CTRL_AUTOINC_EN
0115 | A9MPCORE_GT_CTRL_IRQ_EN
0116 | A9MPCORE_GT_CTRL_COMP_EN
0117 | A9MPCORE_GT_CTRL_TMR_EN;
0118 }
0119
0120 #if defined(RTEMS_SMP) && !defined(CLOCK_DRIVER_USE_ONLY_BOOT_PROCESSOR)
0121 typedef struct {
0122 uint64_t cmpval;
0123 uint32_t interval;
0124 } a9mpcore_clock_init_data;
0125
0126 static void a9mpcore_clock_secondary_action(void *arg)
0127 {
0128 volatile a9mpcore_gt *gt = A9MPCORE_GT;
0129 a9mpcore_clock_init_data *init_data = arg;
0130
0131 a9mpcore_clock_gt_init(gt, init_data->cmpval, init_data->interval);
0132 bsp_interrupt_vector_enable(A9MPCORE_IRQ_GT);
0133 }
0134 #endif
0135
0136 static void a9mpcore_clock_secondary_initialization(
0137 volatile a9mpcore_gt *gt,
0138 uint64_t cmpval,
0139 uint32_t interval
0140 )
0141 {
0142 #if defined(RTEMS_SMP) && !defined(CLOCK_DRIVER_USE_ONLY_BOOT_PROCESSOR)
0143 a9mpcore_clock_init_data init_data = {
0144 .cmpval = cmpval,
0145 .interval = interval
0146 };
0147
0148 _SMP_Othercast_action(a9mpcore_clock_secondary_action, &init_data);
0149
0150 if (cmpval - a9mpcore_clock_get_counter(gt) >= interval) {
0151 bsp_fatal(BSP_ARM_A9MPCORE_FATAL_CLOCK_SMP_INIT);
0152 }
0153 #endif
0154 }
0155
0156 static void a9mpcore_clock_initialize(void)
0157 {
0158 volatile a9mpcore_gt *gt = A9MPCORE_GT;
0159 uint64_t periphclk = a9mpcore_clock_periphclk();
0160 uint64_t us_per_tick = rtems_configuration_get_microseconds_per_tick();
0161 uint32_t interval = (uint32_t) ((periphclk * us_per_tick) / 1000000) - 1;
0162 uint64_t cmpval;
0163
0164 gt->ctrl &= A9MPCORE_GT_CTRL_TMR_EN;
0165 gt->irqst = A9MPCORE_GT_IRQST_EFLG;
0166
0167 cmpval = a9mpcore_clock_get_counter(gt);
0168 cmpval += interval;
0169
0170 a9mpcore_clock_gt_init(gt, cmpval, interval);
0171 a9mpcore_clock_secondary_initialization(gt, cmpval, interval);
0172
0173 a9mpcore_tc.tc_get_timecount = a9mpcore_clock_get_timecount;
0174 a9mpcore_tc.tc_counter_mask = 0xffffffff;
0175 a9mpcore_tc.tc_frequency = periphclk;
0176 a9mpcore_tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER;
0177 rtems_timecounter_install(&a9mpcore_tc);
0178 }
0179
0180 uint32_t _CPU_Counter_frequency(void)
0181 {
0182 return a9mpcore_clock_periphclk();
0183 }
0184
0185 CPU_Counter_ticks _CPU_Counter_read(void)
0186 {
0187 volatile a9mpcore_gt *gt = A9MPCORE_GT;
0188
0189 return gt->cntrlower;
0190 }
0191
0192 #define Clock_driver_support_at_tick(arg) \
0193 a9mpcore_clock_at_tick(arg)
0194
0195 #define Clock_driver_support_initialize_hardware() \
0196 a9mpcore_clock_initialize()
0197
0198 #define Clock_driver_support_install_isr(isr) \
0199 a9mpcore_clock_handler_install(isr)
0200
0201
0202 #include "../../shared/dev/clock/clockimpl.h"