static void null_pointer_protection(void) { #if defined(MPC55XX_BOARD_MPC5674FEVB) || defined(MPC55XX_BOARD_MPC5566EVB) struct MMU_tag mmu = { .MAS0 = { .B = { .TLBSEL = 1, .ESEL = 1 } } }; PPC_SET_SPECIAL_PURPOSE_REGISTER(FSL_EIS_MAS0, mmu.MAS0.R); __asm__ volatile ("tlbre"); mmu.MAS1.R = PPC_SPECIAL_PURPOSE_REGISTER(FSL_EIS_MAS1); mmu.MAS1.B.VALID = 0; PPC_SET_SPECIAL_PURPOSE_REGISTER(FSL_EIS_MAS1, mmu.MAS1.R); __asm__ volatile ("tlbwe"); #endif }
static void null_pointer_protection(void) { #ifdef MPC55XX_NULL_POINTER_PROTECTION struct MMU_tag mmu = { .MAS0 = { .B = { .TLBSEL = 1, .ESEL = 1 } } }; PPC_SET_SPECIAL_PURPOSE_REGISTER(FSL_EIS_MAS0, mmu.MAS0.R); __asm__ volatile ("tlbre"); mmu.MAS1.R = PPC_SPECIAL_PURPOSE_REGISTER(FSL_EIS_MAS1); mmu.MAS1.B.VALID = 0; PPC_SET_SPECIAL_PURPOSE_REGISTER(FSL_EIS_MAS1, mmu.MAS1.R); __asm__ volatile ("tlbwe"); #endif }
void bsp_restart(void *addr) { rtems_interrupt_level level; void (*start)(void) = addr; #ifdef HAS_UBOOT const void *mem_begin = (const void *) bsp_uboot_board_info.bi_memstart; size_t mem_size = bsp_uboot_board_info.bi_memsize; #else /* HAS_UBOOT */ const void *mem_begin = bsp_ram_start; size_t mem_size = (size_t) bsp_ram_size; #endif /* HAS_UBOOT */ uint32_t hid0; rtems_interrupt_disable(level); hid0 = PPC_SPECIAL_PURPOSE_REGISTER(HID0); if ((hid0 & HID0_DCE) != 0) { rtems_cache_flush_multiple_data_lines(mem_begin, mem_size); } hid0 &= ~(HID0_DCE | HID0_ICE); PPC_SET_SPECIAL_PURPOSE_REGISTER(HID0, hid0); (*start)(); }
static void start_thread_if_necessary(uint32_t cpu_index_self) { #if QORIQ_THREAD_COUNT > 1 uint32_t i; for (i = 1; i < QORIQ_THREAD_COUNT; ++i) { uint32_t cpu_index_next = cpu_index_self + i; if ( is_started_by_u_boot(cpu_index_self) && cpu_index_next < rtems_configuration_get_maximum_processors() && _SMP_Should_start_processor(cpu_index_next) ) { /* Thread Initial Next Instruction Address (INIA) */ PPC_SET_THREAD_MGMT_REGISTER(321, (uint32_t) _start_thread); /* Thread Initial Machine State (IMSR) */ PPC_SET_THREAD_MGMT_REGISTER(289, QORIQ_INITIAL_MSR); /* Thread Enable Set (TENS) */ PPC_SET_SPECIAL_PURPOSE_REGISTER(438, 1U << i); } } #endif }
static void t32mppc_clock_initialize(void) { uint64_t frequency = bsp_time_base_frequency / 10; uint32_t us_per_tick = rtems_configuration_get_microseconds_per_tick(); uint32_t interval = (uint32_t) ((frequency * us_per_tick) / 1000000); PPC_SET_SPECIAL_PURPOSE_REGISTER(BOOKE_DECAR, interval - 1); PPC_SET_SPECIAL_PURPOSE_REGISTER_BITS( BOOKE_TCR, BOOKE_TCR_DIE | BOOKE_TCR_ARE ); ppc_set_decrementer_register(interval - 1); t32mppc_clock_tc.tc_get_timecount = t32mppc_clock_get_timecount; t32mppc_clock_tc.tc_counter_mask = 0xffffffff; t32mppc_clock_tc.tc_frequency = bsp_time_base_frequency; t32mppc_clock_tc.tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER; rtems_timecounter_install(&t32mppc_clock_tc); }
static int ppc_clock_exception_handler_booke( BSP_Exception_frame *frame, unsigned number) { uint32_t msr; /* Acknowledge decrementer request */ PPC_SET_SPECIAL_PURPOSE_REGISTER( BOOKE_TSR, BOOKE_TSR_DIS); /* Increment clock ticks */ Clock_driver_ticks += 1; /* Enable external exceptions */ msr = ppc_external_exceptions_enable(); /* Call clock ticker */ ppc_clock_tick(); /* Restore machine state */ ppc_external_exceptions_disable( msr); return 0; }
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; }
void t32mppc_decrementer_dispatch(void) { PPC_SET_SPECIAL_PURPOSE_REGISTER(BOOKE_TSR, BOOKE_TSR_DIS); Clock_isr(NULL); }
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; }
rtems_status_code ppc_exc_initialize( uint32_t interrupt_disable_mask, uintptr_t interrupt_stack_begin, uintptr_t interrupt_stack_size ) { rtems_status_code sc = RTEMS_SUCCESSFUL; const ppc_exc_categories *const categories = ppc_exc_current_categories(); uintptr_t const interrupt_stack_end = interrupt_stack_begin + interrupt_stack_size; uintptr_t interrupt_stack_pointer = interrupt_stack_end - PPC_MINIMUM_STACK_FRAME_SIZE; unsigned vector = 0; uint32_t sda_base = 0; uint32_t r13 = 0; if (categories == NULL) { return RTEMS_NOT_IMPLEMENTED; } /* Assembly code needs SDA_BASE in r13 (SVR4 or EABI). Make sure * early init code put it there. */ __asm__ volatile ( "lis %0, _SDA_BASE_@h\n" "ori %0, %0, _SDA_BASE_@l\n" "mr %1, 13\n" : "=r" (sda_base), "=r"(r13) ); if (sda_base != r13) { return RTEMS_NOT_CONFIGURED; } /* Ensure proper interrupt stack alignment */ interrupt_stack_pointer &= ~((uintptr_t) CPU_STACK_ALIGNMENT - 1); /* Tag interrupt stack bottom */ *(uint32_t *) interrupt_stack_pointer = 0; /* Move interrupt stack values to special purpose registers */ PPC_SET_SPECIAL_PURPOSE_REGISTER(SPRG1, interrupt_stack_pointer); PPC_SET_SPECIAL_PURPOSE_REGISTER(SPRG2, interrupt_stack_begin); ppc_interrupt_set_disable_mask(interrupt_disable_mask); /* Use current MMU / RI settings when running C exception handlers */ ppc_exc_msr_bits = ppc_machine_state_register() & (MSR_DR | MSR_IR | MSR_RI); #ifdef __ALTIVEC__ /* Need vector unit enabled to save/restore altivec context */ ppc_exc_msr_bits |= MSR_VE; #endif if (ppc_cpu_is_bookE() == PPC_BOOKE_STD || ppc_cpu_is_bookE() == PPC_BOOKE_E500) { ppc_exc_initialize_booke(); } for (vector = 0; vector <= LAST_VALID_EXC; ++vector) { ppc_exc_category category = ppc_exc_category_for_vector(categories, vector); if (category != PPC_EXC_INVALID) { void *const vector_address = ppc_exc_vector_address(vector); uint32_t prologue [16]; size_t prologue_size = sizeof(prologue); sc = ppc_exc_make_prologue(vector, category, prologue, &prologue_size); if (sc != RTEMS_SUCCESSFUL) { return RTEMS_INTERNAL_ERROR; } ppc_code_copy(vector_address, prologue, prologue_size); } } /* If we are on a classic PPC with MSR_DR enabled then * assert that the mapping for at least this task's * stack is write-back-caching enabled (see README/CAVEATS) * Do this only if the cache is physically enabled. * Since it is not easy to figure that out in a * generic way we need help from the BSP: BSPs * which run entirely w/o the cache may set * ppc_exc_cache_wb_check to zero prior to calling * this routine. * * We run this check only after exception handling is * initialized so that we have some chance to get * information printed if it fails. * * Note that it is unsafe to ignore this issue; if * the check fails, do NOT disable it unless caches * are always physically disabled. */ if (ppc_exc_cache_wb_check && (MSR_DR & ppc_exc_msr_bits)) { /* The size of 63 assumes cache lines are at most 32 bytes */ uint8_t dummy[63]; uintptr_t p = (uintptr_t) dummy; /* If the dcbz instruction raises an alignment exception * then the stack is mapped as write-thru or caching-disabled. * The low-level code is not capable of dealing with this * ATM. */ p = (p + 31U) & ~31U; __asm__ volatile ("dcbz 0, %0"::"b" (p)); /* If we make it thru here then things seem to be OK */ }