/* * Copyright (C) 2013-2014 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 #if (APPLICATION_IBOOT) static void miu_configure_bridge(const u_int32_t *bridge_settings); #define STATIC_BRIDGE_SHIFT (28) #define STATIC_BRIDGE_OFFSET_MASK ((1 << STATIC_BRIDGE_SHIFT) - 1) #define PMGR_REGISTERS (0 << STATIC_BRIDGE_SHIFT) #define CPU_FABRIC_WIDGETS (1 << STATIC_BRIDGE_SHIFT) #define NRT_FABRIC_WIDGETS (2 << STATIC_BRIDGE_SHIFT) static const u_int32_t bridge_registers[] = { PMGR_BASE_ADDR, CPU_FABRIC_BASE_ADDR, NRT_FABRIC_BASE_ADDR, }; // This array is composed of 3-item tuples consisting of: // Bridge id | register offset (with optional | RECONFIG_RAM_CMD_READ) // Register data value or comparison value if RECONFIG_RAM_CMD_READ is specified // Mask value if RECONFIG_RAM_CMD_READ is specified (used only by reconfig engine) static const u_int32_t bridge_settings_static[] = { CPU_FABRIC_WIDGETS | CPU_Fabric_pl301Wrap0_AMCRDRATELIMIT, 0, 0, CPU_FABRIC_WIDGETS | CPU_Fabric_pl301Wrap0_AMCWRALIMIT, 0, 0, CPU_FABRIC_WIDGETS | CPU_Fabric_pl301Wrap0_AMCRTRLIMIT, (0x3f << 8) | (0x3f << 0), 0, CPU_FABRIC_WIDGETS | CPU_Fabric_pl301Wrap0_AMCWTRLIMIT, (0x3f << 8) | (0x3f << 0), 0, CPU_FABRIC_WIDGETS | CPU_Fabric_pl301Wrap0_SPURDRATELIMIT, 0, 0, CPU_FABRIC_WIDGETS | CPU_Fabric_pl301Wrap0_SPUWRALIMIT, 0, 0, CPU_FABRIC_WIDGETS | CPU_Fabric_pl301Wrap0_SPURTRLIMIT, (0x3f << 8) | (0x3f << 0), 0, CPU_FABRIC_WIDGETS | CPU_Fabric_pl301Wrap0_SPUWTRLIMIT, (0x3f << 8) | (0x3f << 0), 0, CPU_FABRIC_WIDGETS | CPU_Fabric_pl301Wrap0_SPUWGATHER, (0x01 << 8), 0, CPU_FABRIC_WIDGETS | CPU_Fabric_pl301Wrap0_LIOWGATHER, (0x01 << 8), 0, CPU_FABRIC_WIDGETS | CPU_Fabric_pl301Wrap0_AUERDRATELIMIT, 0, 0, CPU_FABRIC_WIDGETS | CPU_Fabric_pl301Wrap0_AUEWRALIMIT, 0, 0, CPU_FABRIC_WIDGETS | CPU_Fabric_pl301Wrap0_AUERTRLIMIT, (0x3f << 8) | (0x3f << 0), 0, CPU_FABRIC_WIDGETS | CPU_Fabric_pl301Wrap0_AUEWTRLIMIT, (0x3f << 8) | (0x3f << 0), 0, CPU_FABRIC_WIDGETS | CPU_Fabric_pl301Wrap0_AUEWGATHER, (0x01 << 8), 0, CPU_FABRIC_WIDGETS | CPU_Fabric_pl301Wrap0_ANSRDRATELIMIT, 0, 0, CPU_FABRIC_WIDGETS | CPU_Fabric_pl301Wrap0_ANSWRALIMIT, 0, 0, CPU_FABRIC_WIDGETS | CPU_Fabric_pl301Wrap0_ANSRTRLIMIT, (0x08 << 8) | (0x08 << 0), 0, CPU_FABRIC_WIDGETS | CPU_Fabric_pl301Wrap0_ANSWTRLIMIT, (0x05 << 8) | (0x05 << 0), 0, CPU_FABRIC_WIDGETS | CPU_Fabric_pl301Wrap0_ANSWGATHER, (0x01 << 8), 0, CPU_FABRIC_WIDGETS | CPU_Fabric_pl301Wrap0_AXI0_ARCHANARBMI0, 0, 0, // Turn on the clock that controls the NRT Fabric widgets. The MSR clock // is behind the Media clock so we turn it on to keep the Media clock // from gating. PMGR_REGISTERS | PMGR_MSR_PS, (0x1 << 8) | (0x1 << 9) | (0xf << 0), 0, PMGR_REGISTERS | PMGR_MEDIA_CLK_CFG, 0x80100000, 0, PMGR_REGISTERS | PMGR_MEDIA_CLK_CFG | RECONFIG_RAM_CMD_READ,0, 0x40000000, NRT_FABRIC_WIDGETS | NRT_Fabric_pl301Wrap1_AMCRDRATELIMIT, 0, 0, NRT_FABRIC_WIDGETS | NRT_Fabric_pl301Wrap1_AMCWRALIMIT, 0, 0, NRT_FABRIC_WIDGETS | NRT_Fabric_pl301Wrap1_AMCRTRLIMIT, (0x3f << 8) | (0x3f << 0), 0, NRT_FABRIC_WIDGETS | NRT_Fabric_pl301Wrap1_AMCWTRLIMIT, (0x3f << 8) | (0x3f << 0), 0, NRT_FABRIC_WIDGETS | NRT_Fabric_pl301Wrap1_MSRRDRATELIMIT, 0, 0, NRT_FABRIC_WIDGETS | NRT_Fabric_pl301Wrap1_MSRWRALIMIT, 0, 0, NRT_FABRIC_WIDGETS | NRT_Fabric_pl301Wrap1_MSRRTRLIMIT, (0x3f << 8) | (0x3f << 0), 0, NRT_FABRIC_WIDGETS | NRT_Fabric_pl301Wrap1_MSRWTRLIMIT, (0x3f << 8) | (0x3f << 0), 0, NRT_FABRIC_WIDGETS | NRT_Fabric_pl301Wrap1_SDIORDRATELIMIT, 0, 0, NRT_FABRIC_WIDGETS | NRT_Fabric_pl301Wrap1_SDIOWRALIMIT, 0, 0, NRT_FABRIC_WIDGETS | NRT_Fabric_pl301Wrap1_SDIORTRLIMIT, (0x3f << 8) | (0x3f << 0), 0, NRT_FABRIC_WIDGETS | NRT_Fabric_pl301Wrap1_SDIOWTRLIMIT, (0x04 << 8) | (0x04 << 0), 0, // Need a read to make sure writes are pushed out to the fabric // before the following steps are executed. NRT_FABRIC_WIDGETS | NRT_Fabric_pl301Wrap1_SDIOWTRLIMIT | RECONFIG_RAM_CMD_READ, (0x04 << 8) | (0x04 << 0), (0xf << 8) | (0xf << 0), // Reprogram the clock configuration to its expected value. // NOTE: We can't write PMGR_MSR_PS back to its original value here. // Attempting to do so will result in a hang. PMGR_REGISTERS | PMGR_MEDIA_CLK_CFG, 0x83100000, 0, PMGR_REGISTERS | PMGR_MEDIA_CLK_CFG | RECONFIG_RAM_CMD_READ,0, 0x40000000, }; #endif // APPLICATION_IBOOT int miu_initialize_internal_ram(void) { #if APPLICATION_SECUREROM // Ensure that rPMGR_SCRATCH0-3 get cleared rPMGR_SCRATCH0 = 0; rPMGR_SCRATCH1 = 0; rPMGR_SCRATCH2 = 0; rPMGR_SCRATCH3 = 0; #endif /* APPLICATION_SECUREROM */ // Save the Security Epoch in the top byte of PMGR_SCRATCH0 rPMGR_SCRATCH0 &= ~0xFF000000; rPMGR_SCRATCH0 |= (platform_get_security_epoch()) << 24; return 0; } int miu_init(void) { #if APPLICATION_IBOOT && !PRODUCT_IBEC // Verify that the Security Epoch in PMGR_SCRATCH0 matches if ((rPMGR_SCRATCH0 >> 24) != platform_get_security_epoch()) { panic("miu_init: Epoch Mismatch\n"); } #endif #if (APPLICATION_IBOOT && !PRODUCT_IBOOT && !PRODUCT_IBEC) miu_configure_bridge(bridge_settings_static); #endif return 0; } void miu_suspend(void) { /* nothing required for suspend */ } int miu_initialize_dram(bool resume) { #if APPLICATION_IBOOT && WITH_HW_AMC mcu_initialize_dram(resume); #endif return 0; } void miu_select_remap(enum remap_select sel) { switch (sel) { case REMAP_SRAM: rPIO_REMAP_CTL = (rPIO_REMAP_CTL & ~1) | (1 << 0); // Resources mapped to address 0x0 are now remapped SPU_SRAM break; case REMAP_SDRAM: rFABRIC_REMAP_REG = (rFABRIC_REMAP_REG & ~1) | (1 << 0); // 0x0000_0000 to 0x0010_0000 is mapped to DRAM break; // reset back to default behavior default: rPIO_REMAP_CTL = 0; rFABRIC_REMAP_REG = 0; break; } } void miu_bypass_prep(void) { } #if (APPLICATION_IBOOT && (PRODUCT_IBSS || PRODUCT_LLB)) static void miu_configure_bridge(const u_int32_t *bridge_settings) { volatile u_int32_t *reg; u_int32_t bridge, offset, data, mask; u_int32_t i; for (i = 0; i < ARRAY_SIZE(bridge_settings_static); i += 3) { bridge = bridge_settings[i] >> STATIC_BRIDGE_SHIFT; offset = bridge_settings[i] & STATIC_BRIDGE_OFFSET_MASK & ~RECONFIG_RAM_CMD_READ; data = bridge_settings[i + 1]; reg = (volatile u_int32_t *)(bridge_registers[bridge] + offset); if (bridge_settings[i] & RECONFIG_RAM_CMD_READ) { mask = bridge_settings_static[i + 2]; SPIN_W_TMO_UNTIL((*reg & mask) == data); } else { *reg = data; } } } #endif // (APPLICATION_IBOOT && (PRODUCT_IBSS || PRODUCT_LLB)) #if APPLICATION_IBOOT void miu_configure_bridge_soc_reconfig_ram(void) { addr_t reg; u_int32_t bridge, offset, data, mask; u_int32_t i; for (i = 0; i < ARRAY_SIZE(bridge_settings_static); i += 3) { bridge = bridge_settings_static[i] >> STATIC_BRIDGE_SHIFT; offset = bridge_settings_static[i] & STATIC_BRIDGE_OFFSET_MASK; data = bridge_settings_static[i + 1]; mask = bridge_settings_static[i + 2]; reg = (addr_t)(bridge_registers[bridge] + offset); reconfig_append_command(RECONFIG_TYPE_SOC, reg, data, mask); } } #endif // APPLICATION_IBOOT #if WITH_DEVICETREE void miu_update_device_tree(DTNode *pmgr_node) { // Nothing to do here } #endif