static void mpc55xx_clock_initialize( void) { volatile struct EMIOS_CH_tag *regs = &EMIOS.CH [MPC55XX_CLOCK_EMIOS_CHANNEL]; union EMIOS_CCR_tag ccr = MPC55XX_ZERO_FLAGS; union EMIOS_CSR_tag csr = MPC55XX_ZERO_FLAGS; unsigned prescaler = mpc55xx_emios_global_prescaler(); uint64_t interval = ((uint64_t) bsp_clock_speed * (uint64_t) rtems_configuration_get_microseconds_per_tick()) / 1000000; /* Apply prescaler */ if (prescaler > 0) { interval /= (uint64_t) prescaler; } else { RTEMS_SYSLOG_ERROR( "unexpected global eMIOS prescaler\n"); } /* Check interval */ if (interval == 0 || interval > MPC55XX_EMIOS_VALUE_MAX) { interval = MPC55XX_EMIOS_VALUE_MAX; RTEMS_SYSLOG_ERROR( "clock timer interval out of range\n"); } /* Configure eMIOS channel */ /* Set channel in GPIO mode */ ccr.B.MODE = MPC55XX_EMIOS_MODE_GPIO_INPUT; regs->CCR.R = ccr.R; /* Clear status flags */ csr.B.OVR = 1; csr.B.OVFL = 1; csr.B.FLAG = 1; regs->CSR.R = csr.R; /* Set timer period */ regs->CADR.R = (uint32_t) interval - 1; /* Set unused registers */ regs->CBDR.R = 0; regs->CCNTR.R = 0; regs->ALTCADR.R = 0; /* Set control register */ ccr.B.MODE = MPC55XX_EMIOS_MODE_MCB_UP_INT_CLK; ccr.B.UCPREN = 1; ccr.B.FEN = 1; ccr.B.FREN = 1; regs->CCR.R = ccr.R; }
static void mpc55xx_dspi_edma_done( mpc55xx_edma_channel_entry *e, uint32_t error_status) { rtems_semaphore_release( e->id); if (error_status != 0) { RTEMS_SYSLOG_ERROR( "eDMA error: 0x%08x\n", error_status); } }
static void mpc55xx_dspi_edma_done( edma_channel_context *ctx, uint32_t error_status) { const mpc55xx_dspi_edma_entry *e = (const mpc55xx_dspi_edma_entry *) ctx; rtems_semaphore_release( e->id); if (error_status != 0) { RTEMS_SYSLOG_ERROR( "eDMA error: 0x%08x\n", error_status); } }
rtems_device_driver Clock_initialize( rtems_device_major_number major, rtems_device_minor_number minor, void *arg) { /* Current CPU type */ ppc_cpu_id_t cpu_type = get_ppc_cpu_type(); /* Make major/minor available to others such as shared memory driver */ rtems_clock_major = major; rtems_clock_minor = minor; /* * Set default ticker. * * The function rtems_clock_tick() returns a status code. This value * will be discarded since the RTEMS documentation claims that it is * always successful. */ ppc_clock_tick = (void (*)(void)) rtems_clock_tick; /* Set the decrementer to the maximum value */ ppc_set_decrementer_register( PPC_CLOCK_DECREMENTER_MAX); /* Decrementer value */ ppc_clock_decrementer_value = bsp_clicks_per_usec * rtems_configuration_get_microseconds_per_tick() - 1; /* Check decrementer value */ if (ppc_clock_decrementer_value == 0) { ppc_clock_decrementer_value = PPC_CLOCK_DECREMENTER_MAX; RTEMS_SYSLOG_ERROR( "decrementer value would be zero, will be set to maximum value instead\n"); } /* Set the nanoseconds since last tick handler */ rtems_clock_set_nanoseconds_extension( ppc_clock_nanoseconds_since_last_tick); if (ppc_cpu_is_bookE()) { /* Set decrementer auto-reload value */ PPC_SET_SPECIAL_PURPOSE_REGISTER( BOOKE_DECAR, ppc_clock_decrementer_value); /* Install exception handler */ ppc_exc_set_handler( ASM_BOOKE_DEC_VECTOR, ppc_clock_exception_handler_booke); /* Enable decrementer and auto-reload */ PPC_SET_SPECIAL_PURPOSE_REGISTER_BITS( BOOKE_TCR, BOOKE_TCR_DIE | BOOKE_TCR_ARE); } else if (cpu_type == PPC_e300c2 || cpu_type == PPC_e300c3) { /* TODO: Not tested for e300c2 */ /* Enable auto-reload */ PPC_SET_SPECIAL_PURPOSE_REGISTER_BITS( HID0, 0x00000040); /* Install exception handler */ ppc_exc_set_handler( ASM_DEC_VECTOR, ppc_clock_exception_handler_e300); } else { /* Here the decrementer value is actually the interval */ ++ppc_clock_decrementer_value; /* Initialize next time base */ ppc_clock_next_time_base = ppc_time_base() + ppc_clock_decrementer_value; /* Install exception handler */ ppc_exc_set_handler( ASM_DEC_VECTOR, ppc_clock_exception_handler_first); } /* Set the decrementer value */ ppc_set_decrementer_register( ppc_clock_decrementer_value); return RTEMS_SUCCESSFUL; }
rtems_device_driver Clock_initialize( rtems_device_major_number major, rtems_device_minor_number minor, void *arg ) { uint64_t frequency = bsp_time_base_frequency; uint64_t us_per_tick = rtems_configuration_get_microseconds_per_tick(); uint32_t interval = (uint32_t) ((frequency * us_per_tick) / 1000000); /* * Set default ticker. */ ppc_clock_tick = rtems_timecounter_tick; if (ppc_cpu_is_bookE() != PPC_BOOKE_405) { /* Decrementer value */ ppc_clock_decrementer_value = interval - 1; /* Check decrementer value */ if (ppc_clock_decrementer_value == 0) { ppc_clock_decrementer_value = PPC_CLOCK_DECREMENTER_MAX; RTEMS_SYSLOG_ERROR( "decrementer value would be zero, will be set to maximum value instead\n"); } if (ppc_cpu_is_bookE()) { /* Set decrementer auto-reload value */ PPC_SET_SPECIAL_PURPOSE_REGISTER( BOOKE_DECAR, ppc_clock_decrementer_value); /* Install exception handler */ ppc_exc_set_handler( ASM_BOOKE_DEC_VECTOR, ppc_clock_exception_handler_booke); /* Enable decrementer and auto-reload */ PPC_SET_SPECIAL_PURPOSE_REGISTER_BITS( BOOKE_TCR, BOOKE_TCR_DIE | BOOKE_TCR_ARE); } else { /* Here the decrementer value is actually the interval */ ++ppc_clock_decrementer_value; /* Initialize next time base */ ppc_clock_next_time_base = ppc_time_base() + ppc_clock_decrementer_value; /* Install exception handler */ ppc_exc_set_handler( ASM_DEC_VECTOR, ppc_clock_exception_handler_first); } /* Set the decrementer value */ ppc_set_decrementer_register( ppc_clock_decrementer_value); } else { /* PIT interval value */ ppc_clock_decrementer_value = interval; /* Install exception handler */ ppc_exc_set_handler(ASM_BOOKE_DEC_VECTOR, ppc_clock_exception_handler_ppc405); /* Enable PIT and auto-reload */ PPC_SET_SPECIAL_PURPOSE_REGISTER_BITS(PPC405_TCR, BOOKE_TCR_DIE | BOOKE_TCR_ARE); /* Set PIT auto-reload and initial value */ PPC_SET_SPECIAL_PURPOSE_REGISTER(PPC405_PIT, interval); } /* Install timecounter */ ppc_tc.tc_get_timecount = ppc_get_timecount; ppc_tc.tc_counter_mask = 0xffffffff; ppc_tc.tc_frequency = frequency; ppc_tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER; rtems_timecounter_install(&ppc_tc); return RTEMS_SUCCESSFUL; }