217 lines
7.6 KiB
C
217 lines
7.6 KiB
C
/*
|
|
* 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 <arch.h>
|
|
#include <debug.h>
|
|
#include <drivers/miu.h>
|
|
#include <platform.h>
|
|
#include <platform/memmap.h>
|
|
#include <platform/miu.h>
|
|
#include <platform/soc/chipid.h>
|
|
#include <platform/soc/miu.h>
|
|
#include <platform/soc/pmgr.h>
|
|
#include <platform/soc/reconfig.h>
|
|
#include <platform/clocks.h>
|
|
#include <platform/soc/hwclocks.h>
|
|
#include <platform/timer.h>
|
|
|
|
#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
|