/* * Copyright (C) 2010 Apple Inc. All rights reserved. * * This document is the property of Apple Inc. * It is considered confidential and proprietary. * * This document may not be reproduced or transmitted in any form, * in whole or in part, without the express written permission of * Apple Inc. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* * Platform memory layout. * * The IOP sees SDRAM at its physical location uncached, and has an cached aperture * visible elsewhere. SDRAM size of up to 1GB is currently supported. * SRAM is not visible/legally usable. * * For some platforms/targets, SDRAM_LEN is not constant and so we * have to compute a maximum via other means. * * Note that the AE2 Sparrow shares this code. */ #define MEM_CACHED_BASE (SDRAM_BASE | 0xc0000000) #define SDRAM_MAX_LEN (SDRAM_BANK_LEN * SDRAM_BANK_COUNT) struct mem_static_map_entry mem_static_map_entries[] = { { MEM_CACHED_BASE, /* cached */ SDRAM_BASE, /* uncached */ SDRAM_BASE, /* physical */ SDRAM_MAX_LEN /* length */ }, {MAP_NO_ENTRY, MAP_NO_ENTRY, MAP_NO_ENTRY, 0} }; void platform_mmu_setup(bool resume) { if (false == resume) { /* Note: sharing settings aren't critical, as SCC doesn't see the AxUSER bits * and the AxCACHE widget does all the heavy lifting. */ /* Remap text base to zero, outer uncacheable, shared */ arm_mmu_map_section(0, TEXT_BASE, kARMMMUInnerNormalOuterNoncached, true); /* Remap all of SDRAM through the cacheable aperture, outer uncacheable, shared */ arm_mmu_map_section_range(MEM_CACHED_BASE, SDRAM_BASE, ROUNDUP(SDRAM_BANK_LEN * SDRAM_BANK_COUNT, MB)/MB, kARMMMUInnerNormalOuterNoncached, true, false); /* Remap all of SDRAM through the uncacheable aperture (existing mappings should be there, but be sure) */ arm_mmu_map_section_range(SDRAM_BASE, SDRAM_BASE, ROUNDUP(SDRAM_BANK_LEN * SDRAM_BANK_COUNT, MB)/MB, kARMMMUStronglyOrdered, false, false); } } bool platform_get_production_mode(void) { return(true); } bool platform_get_secure_mode(void) { return(true); } void platform_reset(bool panic) { for (;;) ; } /* * Early init is done every time the IOP starts. */ int platform_early_init() { #if PLATFORM_VARIANT_IOP /* In general we want power-gating to be disabled. */ rPMGR_PWR_GATE_CTL_CLR = PMGR_PWR_GATE_IOP; while (rPMGR_PWR_GATE_CTL_CLR & PMGR_PWR_GATE_IOP) ; #endif interrupt_init(); timer_init(0); return(0); } /* * Halt waiting for an interrupt. */ void platform_halt(void) { arch_halt(); } #if SUPPORT_SLEEP #if WITH_IOP_POWER_GATING /* * Deep idle sleep with power gating */ void platform_deep_idle(void) { rPMGR_PWR_GATE_CTL_SET = PMGR_PWR_GATE_IOP; while (!(rPMGR_PWR_GATE_CTL_SET & PMGR_PWR_GATE_IOP)) ; a5iop_sleep(1); rPMGR_PWR_GATE_CTL_CLR = PMGR_PWR_GATE_IOP; while (rPMGR_PWR_GATE_CTL_CLR & PMGR_PWR_GATE_IOP) ; } #endif void platform_sleep(void) { /* We assume power-gating is disabled, which it need to be so * the IOP wrapper registers don't disappear. */ a5iop_sleep(0); } #endif /* * Cache control */ void platform_cache_operation(int operation, void *address, u_int32_t length) { /* Wrap the operation with interrupt disable to avoid * reentrance (while allowing the low-level cacheop function * to be used without bumping the IRQ disable level) */ enter_critical_section(); a5iop_cache_operation(operation, address, length); exit_critical_section(); } /* * Host doorbell uses a SWI in the AIC. */ static void (* _doorbell_handler)(void *arg); static void platform_doorbell_handler(void *arg) { /* clear the doorbell before passing up */ interrupt_clear_ipc(INT_IOP); _doorbell_handler(arg); } void platform_init_iop_doorbell(void (* handler)(void *arg), void *arg) { _doorbell_handler = handler; install_int_handler(INT_IOP, platform_doorbell_handler, arg); set_int_type(INT_IOP, INT_TYPE_IRQ | INT_TYPE_LEVEL); unmask_int(INT_IOP); } void platform_mask_doorbell(void) { mask_int(INT_IOP); } void platform_unmask_doorbell(void) { unmask_int(INT_IOP); } void platform_ring_host_doorbell(void) { interrupt_generate_ipc(INT_HOST); } int platform_init_nmi(void (*handler)(void *arg), void *arg) { #ifdef INT_IOP_NMI install_int_handler(INT_IOP_NMI, handler, arg); set_int_type(INT_IOP_NMI, INT_TYPE_FIQ | INT_TYPE_LEVEL); unmask_int(INT_IOP_NMI); #endif return(0); } /* * Clock management. * * Currently the IOP does none for this platform. */ void clock_gate(int device, bool enable) { }