File indexing completed on 2025-05-11 08:23:54
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 #include <bsp.h>
0037 #include <bsp/fatal.h>
0038 #include <bsp/irq.h>
0039
0040 #include <mpc55xx/regs.h>
0041
0042 #include <rtems/timecounter.h>
0043
0044 static rtems_timecounter_simple mpc55xx_tc;
0045
0046 #if defined(MPC55XX_CLOCK_EMIOS_CHANNEL)
0047
0048 #include <mpc55xx/emios.h>
0049
0050 static uint32_t mpc55xx_tc_get(rtems_timecounter_simple *tc)
0051 {
0052 return EMIOS.CH [MPC55XX_CLOCK_EMIOS_CHANNEL].CCNTR.R;
0053 }
0054
0055 static bool mpc55xx_tc_is_pending(rtems_timecounter_simple *tc)
0056 {
0057 return EMIOS.CH [MPC55XX_CLOCK_EMIOS_CHANNEL].CSR.B.FLAG != 0;
0058 }
0059
0060 static uint32_t mpc55xx_tc_get_timecount(struct timecounter *tc)
0061 {
0062 return rtems_timecounter_simple_upcounter_get(
0063 tc,
0064 mpc55xx_tc_get,
0065 mpc55xx_tc_is_pending
0066 );
0067 }
0068
0069 static void mpc55xx_tc_at_tick(rtems_timecounter_simple *tc)
0070 {
0071 union EMIOS_CSR_tag csr = MPC55XX_ZERO_FLAGS;
0072 csr.B.FLAG = 1;
0073 EMIOS.CH [MPC55XX_CLOCK_EMIOS_CHANNEL].CSR.R = csr.R;
0074 }
0075
0076 static void mpc55xx_tc_tick(rtems_timecounter_simple *tc)
0077 {
0078 rtems_timecounter_simple_upcounter_tick(
0079 tc,
0080 mpc55xx_tc_get,
0081 mpc55xx_tc_at_tick
0082 );
0083 }
0084
0085 static void mpc55xx_clock_handler_install(rtems_interrupt_handler handler)
0086 {
0087 rtems_status_code sc = RTEMS_SUCCESSFUL;
0088
0089 sc = mpc55xx_interrupt_handler_install(
0090 MPC55XX_IRQ_EMIOS(MPC55XX_CLOCK_EMIOS_CHANNEL),
0091 "clock",
0092 RTEMS_INTERRUPT_UNIQUE,
0093 MPC55XX_INTC_MIN_PRIORITY,
0094 handler,
0095 &mpc55xx_tc
0096 );
0097 if (sc != RTEMS_SUCCESSFUL) {
0098 bsp_fatal(MPC55XX_FATAL_CLOCK_EMIOS_IRQ_INSTALL);
0099 }
0100 }
0101
0102 static void mpc55xx_clock_initialize(void)
0103 {
0104 volatile struct EMIOS_CH_tag *regs = &EMIOS.CH [MPC55XX_CLOCK_EMIOS_CHANNEL];
0105 union EMIOS_CCR_tag ccr = MPC55XX_ZERO_FLAGS;
0106 union EMIOS_CSR_tag csr = MPC55XX_ZERO_FLAGS;
0107 unsigned prescaler = mpc55xx_emios_global_prescaler();
0108 uint64_t reference_clock = bsp_clock_speed;
0109 uint64_t us_per_tick = rtems_configuration_get_microseconds_per_tick();
0110 uint64_t interval = (reference_clock * us_per_tick) / 1000000;
0111
0112
0113 if (prescaler > 0) {
0114 interval /= (uint64_t) prescaler;
0115 } else {
0116 bsp_fatal(MPC55XX_FATAL_CLOCK_EMIOS_PRESCALER);
0117 }
0118
0119
0120 if (interval == 0 || interval > MPC55XX_EMIOS_VALUE_MAX) {
0121 bsp_fatal(MPC55XX_FATAL_CLOCK_EMIOS_INTERVAL);
0122 }
0123
0124
0125
0126
0127 ccr.B.MODE = MPC55XX_EMIOS_MODE_GPIO_INPUT;
0128 regs->CCR.R = ccr.R;
0129
0130
0131 csr.B.OVR = 1;
0132 csr.B.OVFL = 1;
0133 csr.B.FLAG = 1;
0134 regs->CSR.R = csr.R;
0135
0136
0137 regs->CCNTR.R = 1;
0138
0139
0140 regs->CADR.R = (uint32_t) interval - 1;
0141
0142
0143 #if MPC55XX_CHIP_FAMILY == 551
0144 ccr.B.MODE = MPC55XX_EMIOS_MODE_MCB_UP_INT_CLK;
0145 #else
0146 ccr.B.MODE = MPC55XX_EMIOS_MODE_MC_UP_INT_CLK;
0147 #endif
0148 ccr.B.UCPREN = 1;
0149 ccr.B.FEN = 1;
0150 ccr.B.FREN = 1;
0151 regs->CCR.R = ccr.R;
0152
0153 rtems_timecounter_simple_install(
0154 &mpc55xx_tc,
0155 reference_clock,
0156 interval,
0157 mpc55xx_tc_get_timecount
0158 );
0159 }
0160
0161 #elif defined(MPC55XX_CLOCK_PIT_CHANNEL)
0162
0163 static uint32_t mpc55xx_tc_get(rtems_timecounter_simple *tc)
0164 {
0165 return PIT_RTI.CHANNEL [MPC55XX_CLOCK_PIT_CHANNEL].CVAL.R;
0166 }
0167
0168 static bool mpc55xx_tc_is_pending(rtems_timecounter_simple *tc)
0169 {
0170 return PIT_RTI.CHANNEL [MPC55XX_CLOCK_PIT_CHANNEL].TFLG.B.TIF != 0;
0171 }
0172
0173 static uint32_t mpc55xx_tc_get_timecount(struct timecounter *tc)
0174 {
0175 return rtems_timecounter_simple_downcounter_get(
0176 tc,
0177 mpc55xx_tc_get,
0178 mpc55xx_tc_is_pending
0179 );
0180 }
0181
0182 static void mpc55xx_tc_at_tick(rtems_timecounter_simple *tc)
0183 {
0184 volatile PIT_RTI_CHANNEL_tag *channel =
0185 &PIT_RTI.CHANNEL [MPC55XX_CLOCK_PIT_CHANNEL];
0186 PIT_RTI_TFLG_32B_tag tflg = { .B = { .TIF = 1 } };
0187
0188 channel->TFLG.R = tflg.R;
0189 }
0190
0191 static void mpc55xx_tc_tick(rtems_timecounter_simple *tc)
0192 {
0193 rtems_timecounter_simple_downcounter_tick(
0194 tc,
0195 mpc55xx_tc_get,
0196 mpc55xx_tc_at_tick
0197 );
0198 }
0199
0200 static void mpc55xx_clock_handler_install(rtems_interrupt_handler handler)
0201 {
0202 rtems_status_code sc = RTEMS_SUCCESSFUL;
0203
0204 sc = mpc55xx_interrupt_handler_install(
0205 MPC55XX_IRQ_PIT_CHANNEL(MPC55XX_CLOCK_PIT_CHANNEL),
0206 "clock",
0207 RTEMS_INTERRUPT_UNIQUE,
0208 MPC55XX_INTC_MIN_PRIORITY,
0209 handler,
0210 &mpc55xx_tc
0211 );
0212 if (sc != RTEMS_SUCCESSFUL) {
0213 bsp_fatal(MPC55XX_FATAL_CLOCK_PIT_IRQ_INSTALL);
0214 }
0215 }
0216
0217 static void mpc55xx_clock_initialize(void)
0218 {
0219 volatile PIT_RTI_CHANNEL_tag *channel =
0220 &PIT_RTI.CHANNEL [MPC55XX_CLOCK_PIT_CHANNEL];
0221 uint64_t reference_clock = bsp_clock_speed;
0222 uint64_t us_per_tick = rtems_configuration_get_microseconds_per_tick();
0223 uint64_t interval = (reference_clock * us_per_tick) / 1000000;
0224 PIT_RTI_PITMCR_32B_tag pitmcr = { .B = { .FRZ = 1 } };
0225 PIT_RTI_TCTRL_32B_tag tctrl = { .B = { .TIE = 1, .TEN = 1 } };
0226
0227 PIT_RTI.PITMCR.R = pitmcr.R;
0228 channel->LDVAL.R = interval;
0229 channel->TCTRL.R = tctrl.R;
0230
0231 rtems_timecounter_simple_install(
0232 &mpc55xx_tc,
0233 reference_clock,
0234 interval,
0235 mpc55xx_tc_get_timecount
0236 );
0237 }
0238
0239 #endif
0240
0241 #define Clock_driver_timecounter_tick(arg) mpc55xx_tc_tick(arg)
0242 #define Clock_driver_support_initialize_hardware() \
0243 mpc55xx_clock_initialize()
0244 #define Clock_driver_support_install_isr(isr) \
0245 mpc55xx_clock_handler_install(isr)
0246
0247
0248 #include "../../../shared/dev/clock/clockimpl.h"