566 lines
22 KiB
C
566 lines
22 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 <debug.h>
|
|
#include <drivers/amc/amc.h>
|
|
#include <drivers/amc/amc_phy.h>
|
|
#include <drivers/amc/amc_regs.h>
|
|
#include <drivers/amp/amp_v2.h>
|
|
#include <drivers/amp/amp_v2_calibration.h>
|
|
#include <drivers/dram.h>
|
|
#include <drivers/miu.h>
|
|
#include <sys.h>
|
|
#include <platform/soc/hwclocks.h>
|
|
#include <platform/soc/reconfig.h>
|
|
|
|
int mcu_initialize_dram (bool resume)
|
|
{
|
|
return amc_init(resume);
|
|
}
|
|
|
|
void mcu_bypass_prep (int step)
|
|
{
|
|
amc_phy_bypass_prep(step);
|
|
}
|
|
|
|
uint64_t mcu_get_memory_size (void)
|
|
{
|
|
return amc_get_memory_size();
|
|
}
|
|
|
|
void amc_configure_address_decoding_and_mapping (void)
|
|
{
|
|
rAMC_ADDRCFG = amc_params.addrcfg;
|
|
|
|
rAMC_CHNLDEC = amc_params.chnldec;
|
|
|
|
rAMC_ADDRMAP_MODE = 2; // RIBI2
|
|
|
|
rAMC_AIU_ADDRBANKHASH2 = amc_params.bankhash2;
|
|
rAMC_AIU_ADDRBANKHASH1 = amc_params.bankhash1;
|
|
rAMC_AIU_ADDRBANKHASH0 = amc_params.bankhash0;
|
|
}
|
|
|
|
void amc_enable_slow_boot (bool enable)
|
|
{
|
|
if (enable) {
|
|
// switch to slow clock
|
|
clocks_set_performance(kPerformanceMemoryLow);
|
|
spin(1);
|
|
} else {
|
|
#if !SUPPORT_FPGA
|
|
// switch back to full-speed
|
|
clocks_set_performance(kPerformanceMemoryFull);
|
|
spin(1);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
// Some AMC features to be changed before calibration starts, and restored after calibration is complete
|
|
void amc_calibration_start(bool start)
|
|
{
|
|
if (start)
|
|
// Disable OdtsRdIntrvl
|
|
rAMC_ODTS &= 0xFFFFFC00;
|
|
else
|
|
// Re-enable OdtsRdIntrvl
|
|
rAMC_ODTS |= amc_params.odts;
|
|
}
|
|
|
|
void amc_enable_rddqcal(bool enable)
|
|
{
|
|
if (enable)
|
|
rAMC_READ_LEVELING |= 1;
|
|
else
|
|
rAMC_READ_LEVELING &= ~1;
|
|
}
|
|
|
|
void amc_wrdqcal_start(bool start)
|
|
{
|
|
if (start) {
|
|
// Enable WriteMergeEn and WqInOrderEn
|
|
rAMC_PSQWQCTL0 = (1 << 8) | (1 << 0);
|
|
|
|
// Set SelfRefTmrVal to max
|
|
rAMC_PWRMNGTPARAM |= (0xFFFF << 16);
|
|
|
|
// Designer suggests 0xBB, so that writes do not age out
|
|
rAMC_PSQWQCTL1 = 0xBB;
|
|
} else {
|
|
rAMC_PSQWQCTL0 = 0x00010100;
|
|
rAMC_PWRMNGTPARAM = amc_params.pwrmngtparam_guided;
|
|
// WqAgeOutVal has to be set to 3/4 of SelfRefTmrVal
|
|
rAMC_PSQWQCTL1 = (3 * ((amc_params.pwrmngtparam_guided & 0xFFFF0000) >> 16)) >> 2;
|
|
|
|
// Enabling AutoSR only after wrdqcal is done
|
|
rAMC_PWRMNGTEN |= 0x00011011;
|
|
}
|
|
}
|
|
|
|
void amc_finalize (bool resume)
|
|
{
|
|
rAMC_AREFPARAM |= 0x00001800;
|
|
|
|
rAMC_QBREN = 0x00110001;
|
|
|
|
if (!resume) {
|
|
#if SUPPORT_FPGA
|
|
rAMC_ODTS = amc_params.odts;
|
|
#else
|
|
rAMC_ODTS = 0x00010000 | amc_params.odts;
|
|
#endif
|
|
amc_enable_autorefresh();
|
|
}
|
|
|
|
rAMC_ZQC = 0x010c03ff;
|
|
#if !SUPPORT_FPGA
|
|
rAMC_AIUPRT_RD_CWF = 0x00323200;
|
|
#endif
|
|
rAMC_QBRPARAM = 0x00510000;
|
|
rAMC_QBREN = 0x00111001;
|
|
|
|
rAMC_PSQWQCTL0 = 0x00010100;
|
|
|
|
#if SUPPORT_FPGA
|
|
rAMC_PWRMNGTEN = 0x00110010;
|
|
#else
|
|
rAMC_PWRMNGTEN = 0x00111011;
|
|
rAMC_PWRMNGTPARAM = amc_params.pwrmngtparam_guided;
|
|
#endif
|
|
}
|
|
|
|
void amc_dram_workarounds (bool resume)
|
|
{
|
|
const struct amc_memory_device_info *dev_info;
|
|
|
|
dev_info = amc_get_memory_device_info();
|
|
|
|
switch (dev_info->vendor_id) {
|
|
case JEDEC_MANUF_ID_HYNIX:
|
|
// No work-arounds for Hynix ... yet!
|
|
break;
|
|
|
|
case JEDEC_MANUF_ID_ELPIDA:
|
|
/* Filter only for Elpida 25nm to apply test MRS */
|
|
if ((dev_info->rev_id == 0x2) && (dev_info->rev_id2 <= 0x2)) { // MR6 = 2(25nm) and MR7 = 2(Rev2)
|
|
if (!resume) {
|
|
// Elpida has no TestMRS entry/exit cmd
|
|
// <rdar://problem/15465954> Fiji: Need Duty Cycle Adjust work-around to improve Fiji+Elpida 25nm DDR eye margin
|
|
amc_mrcmd(MR_WRITE, AMC_NUM_CHANNELS, AMC_NUM_RANKS, 0x9, 0xbb);
|
|
amc_mrcmd(MR_WRITE, AMC_NUM_CHANNELS, AMC_NUM_RANKS, 0x9, 0x27);
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
// Shift dq offset as needed.
|
|
// In the future, it's possible the shift value changes based on SOC or DRAM vendor.
|
|
// Thus, we need to have this function per SOC.
|
|
void amc_dram_shift_dq_offset (int8_t *dq_offset, uint8_t num_bytes) {
|
|
int8_t shift_val;
|
|
uint8_t i;
|
|
const struct amc_memory_device_info *dev_info;
|
|
|
|
dev_info = amc_get_memory_device_info();
|
|
|
|
// No shifts defined by SEG yet for M7
|
|
switch (dev_info->vendor_id) {
|
|
case JEDEC_MANUF_ID_HYNIX:
|
|
case JEDEC_MANUF_ID_SAMSUNG:
|
|
case JEDEC_MANUF_ID_ELPIDA:
|
|
default:
|
|
shift_val = 0;
|
|
break;
|
|
}
|
|
|
|
if (shift_val)
|
|
for (i = 0; i < num_bytes; i++)
|
|
dq_offset[i] += shift_val;
|
|
}
|
|
#if WITH_HW_RECONFIG
|
|
|
|
#define CALIB_TYPE_CAWRLVL 0
|
|
#define CALIB_TYPE_DQWRLVL 1
|
|
|
|
// <rdar://problem/16356260> M7 MEM Reconfig sequence: remove phyupdates
|
|
#if 0
|
|
static void amp_phy_update_reconfig(uint32_t update)
|
|
{
|
|
// Release CKE and disable phyupdt to allow normal operation
|
|
if (!update)
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_TESTMODE(AMP_CA,0), 0, 0);
|
|
|
|
// issue phyupdt to block AMC traffic
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_CAPHYUPDTCRTL(0), update, 0);
|
|
|
|
// wait for the phyupdt change to take effect. there is only 1 bit in the status reg: bit 0.
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, ((addr_t) &rAMP_CAPHYUPDTSTATUS(0)) | RECONFIG_RAM_CMD_READ, (update & 1), 1);
|
|
|
|
// CKE must be low when updating dlysel to avoid glitches
|
|
if (update)
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_TESTMODE(AMP_CA,0), TESTMODE_FORCECKELOW, 0);
|
|
}
|
|
#endif
|
|
|
|
static void amp_wrlvl_program_reconfig(uint32_t calib_type, uint32_t byte)
|
|
{
|
|
addr_t codeaddr, dlyaddr;
|
|
uint32_t code, dly;
|
|
|
|
if (calib_type == CALIB_TYPE_CAWRLVL) {
|
|
codeaddr = (addr_t) &rAMP_CAWRLVLSDLLCODE(0);
|
|
code = rAMP_CAWRLVLSDLLCODE(0);
|
|
dlyaddr = (addr_t) &rAMP_CAWRLVLCLKDLYSEL(0);
|
|
dly = rAMP_CAWRLVLCLKDLYSEL(0);
|
|
} else {
|
|
codeaddr = (addr_t) &rAMP_DQWRLVLSDLLCODE(0, byte);
|
|
dlyaddr = (addr_t) &rAMP_DQWRLVLDLYCHAINCTRL(0, byte);
|
|
code = rAMP_DQWRLVLSDLLCODE(0, byte);
|
|
dly = rAMP_DQWRLVLDLYCHAINCTRL(0, byte);
|
|
}
|
|
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, codeaddr, code, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, dlyaddr, dly, 0);
|
|
}
|
|
|
|
void amc_configure_mem_reconfig_ram(void)
|
|
{
|
|
uint32_t f, i;
|
|
#if !SUPPORT_FPGA
|
|
uint32_t byte, bit;
|
|
#endif
|
|
|
|
/* Step 1: AMC Initial Configuration */
|
|
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_DLLSTS(AMP_DQ,0), 0x00017307, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_DLLSTS(AMP_CA,0), 0x00017307, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_LAT, (amc_params.rdlat << 16) | (amc_params.wrlat << 8), 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_PHYRDWRTIM, (amc_params.phywrlat << 16) | (amc_params.phyrdlat << 8) | (amc_params.rdlat - 2), 0);
|
|
|
|
for(f = 0; f < AMC_FREQUENCY_SLOTS; f++) {
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_CAS_FREQ(f), amc_params.freq[f].cas, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_PCH_FREQ(f), amc_params.freq[f].pch, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_ACT_FREQ(f), amc_params.freq[f].act, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_AUTO_FREQ(f), amc_params.freq[f].autoref | ((f == 0) ? amc_params.tREFi : 0), 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_SELF_FREQ(f), amc_params.freq[f].selfref, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_MODE_FREQ(f), amc_params.freq[f].modereg, 0);
|
|
}
|
|
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_AUTOREF_PARAMS, amc_params.autoref_params, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_PDN, amc_params.pdn, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_DERATE, amc_params.derate, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_RD, amc_params.read, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_BUSTAT, amc_params.bustat, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_BUSTAT_FREQ23, amc_params.bustat2, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_TREFBWBASECYC_FREQ(0), amc_params.freq[0].trefbwbasecyc, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_TREFBWBASECYC_FREQ(1), amc_params.freq[1].trefbwbasecyc, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_TREFBWBASECYC_FREQ(2), amc_params.freq[2].trefbwbasecyc, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_MIFCASSCH_FREQ(0), amc_params.freq[0].mifcassch, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_CH0RNKCFG0, 1, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_PWRMNGTEN, amc_params.pwrmngten_default, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_SCHEN, amc_params.schen_default, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_MCPHY_UPDTPARAM1, amc_params.mcphyupdate1, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_MCPHY_UPDTPARAM, amc_params.mcphyupdate, 0);
|
|
|
|
// AMCEN
|
|
{
|
|
uint32_t amc_en = 0x00000001;
|
|
|
|
if (amc_params.flags & FLAG_AMC_PARAM_LEGACY)
|
|
{
|
|
amc_en |= 0x80000000;
|
|
}
|
|
if (amc_params.flags & FLAG_AMC_PARAM_ENABLE_AIU)
|
|
{
|
|
amc_en |= 0x10000;
|
|
}
|
|
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_AMCEN, amc_en, 0);
|
|
}
|
|
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_AIU_ADDRBANKHASH2, amc_params.bankhash2, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_AIU_ADDRBANKHASH1, amc_params.bankhash1, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_AIU_ADDRBANKHASH0, amc_params.bankhash0, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_ADDRMAP_MODE, 2, 0);
|
|
|
|
/* Step 2: AMP Initial Configurations */
|
|
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_AMPEN(AMP_CA,0), 1, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_AMPEN(AMP_DQ,0), 1, 0);
|
|
|
|
#if !SUPPORT_FPGA
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_DQDQSDS(0), amc_phy_params.drive_strength, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_NONDQDS(0), amc_phy_params.drive_strength, 0);
|
|
#endif
|
|
// DIFFMODE_FREQ[n], n=0..3
|
|
for(f = 0; f < AMP_FREQUENCY_SLOTS; f++)
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_DIFFMODE_FREQ(0,f), 0x00000121, 0);
|
|
|
|
#if !SUPPORT_FPGA
|
|
// RDnDQm_DESKEW_CTRL, n=0..3, m=0..7
|
|
for(byte = 0; byte < AMP_MAX_RD; byte++)
|
|
for(bit = 0; bit < AMP_MAX_DQ; bit++)
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_RDDQDESKEW_CTRL(0, byte, bit), 0x00000006, 0);
|
|
|
|
// DLLLOCKTIM
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_DLLLOCKTIM(AMP_CA,0), 0x000d0013, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_DLLLOCKTIM(AMP_DQ,0), 0x000d0013, 0);
|
|
#endif
|
|
|
|
for(f = 0; f < AMP_FREQUENCY_SLOTS; f++) {
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_CAOUTDLLSCL_FREQ(0,f), amc_phy_params.freq[f].caoutdllscl, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_DQSINDLLSCL_FREQ(0,f), amc_phy_params.freq[f].dqsindllscl, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_RDCAPCFG_FREQ(AMP_DQ,0,f), amc_phy_params.freq[f].rdcapcfg, 0);
|
|
}
|
|
|
|
#if !SUPPORT_FPGA
|
|
// DLLUPDTCTRL
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_DLLUPDTCTRL(AMP_CA,0), 0x00017507, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_DLLUPDTCTRL(AMP_DQ,0), 0x00017507, 0);
|
|
// IMPAUTOCAL
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_IMPAUTOCAL(AMP_DQ,0), amc_phy_params.imp_auto_cal, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_IMPAUTOCAL(AMP_CA,0), amc_phy_params.imp_auto_cal, 0);
|
|
#endif
|
|
|
|
// DLLUPDTINTVL
|
|
#if !SUPPORT_FPGA
|
|
uint32_t dllupdtintvl = 0x10200000;
|
|
#else
|
|
uint32_t dllupdtintvl = 0;
|
|
#endif
|
|
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_DLLUPDTINTVL(AMP_CA,0), dllupdtintvl, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_DLLUPDTINTVL(AMP_DQ,0), dllupdtintvl, 0);
|
|
|
|
// DLLEN sequence
|
|
#if !SUPPORT_FPGA
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_DLLEN(AMP_CA,0), 0x00000100, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_DLLEN(AMP_DQ,0), 0x00000100, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_DLLEN(AMP_CA,0), 0x00000101, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_DLLEN(AMP_DQ,0), 0x00000101, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_DLLEN(AMP_CA,0), 0x00000100, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_DLLEN(AMP_DQ,0), 0x00000100, 0);
|
|
#endif
|
|
|
|
// MDLLFREQBINDISABLE
|
|
#if !SUPPORT_FPGA
|
|
uint32_t mdllfreqbindisable = 0x00000008;
|
|
#else
|
|
uint32_t mdllfreqbindisable = 0x0000000f;
|
|
#endif
|
|
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_MDLLFREQBINDISABLE(AMP_CA,0), mdllfreqbindisable, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_MDLLFREQBINDISABLE(AMP_DQ,0), mdllfreqbindisable, 0);
|
|
|
|
// DLLUPDTCMD
|
|
#if !SUPPORT_FPGA
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_DLLUPDTCMD(AMP_CA,0), 0x00000001, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_DLLUPDTCMD(AMP_DQ,0), 0x00000001, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, ((addr_t) &rAMP_DLLUPDTCMD(AMP_CA,0)) | RECONFIG_RAM_CMD_READ, 0, 1);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, ((addr_t) &rAMP_DLLUPDTCMD(AMP_DQ,0)) | RECONFIG_RAM_CMD_READ, 0, 1);
|
|
#endif
|
|
|
|
// AMPINIT
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_AMPINIT(AMP_CA,0), 0x00000001, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_AMPINIT(AMP_DQ,0), 0x00000001, 0);
|
|
// IMPCALCMD sequence
|
|
#if !SUPPORT_FPGA
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_IMPCALCMD(AMP_CA,0), 0x00000101, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_IMPCALCMD(AMP_DQ,0), 0x00000101, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, ((addr_t) &rAMP_IMPCALCMD(AMP_CA,0)) | RECONFIG_RAM_CMD_READ, 0, 1);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, ((addr_t) &rAMP_IMPCALCMD(AMP_DQ,0)) | RECONFIG_RAM_CMD_READ, 0, 1);
|
|
#endif
|
|
|
|
/* Step 3: Self-Refresh Exit */
|
|
|
|
#if !SUPPORT_FPGA
|
|
/* CA calibration offsets */
|
|
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_CASDLLCTRL(0), (1 << 24) | (rAMP_CASDLLCTRL(0)), 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, ((addr_t) &rAMP_CASDLLCTRL(0)) | RECONFIG_RAM_CMD_READ, 0, (1 << 24));
|
|
|
|
for (bit = 0; bit < CA_NUM_BITS; bit++)
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_CADESKEW_CTRL(0,bit), rAMP_CADESKEW_CTRL(0,bit), 0);
|
|
|
|
// ck: skip if 0, since that is reset value
|
|
uint32_t caclk = rAMP_CKDESKEW_CTRL(0);
|
|
if (caclk) {
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_TESTMODE(AMP_CA,0), TESTMODE_FORCECKELOW, 0);
|
|
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_DRAMSIGDLY(AMP_CA, 0, 0), rAMP_DRAMSIGDLY(AMP_CA, 0, 0), 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_CSDESKEW_CTRL(0), caclk, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_CKDESKEW_CTRL(0), caclk, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_CKEDESKEW_CTRL(0), caclk, 0);
|
|
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_TESTMODE(AMP_CA,0), 0, 0);
|
|
}
|
|
|
|
/* WrLvl calibration offsets */
|
|
|
|
amp_wrlvl_program_reconfig(CALIB_TYPE_CAWRLVL, 0);
|
|
for (byte = 0; byte < DQ_NUM_BYTES; byte++)
|
|
amp_wrlvl_program_reconfig(CALIB_TYPE_DQWRLVL, byte);
|
|
#endif
|
|
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_AREFPARAM, amc_params.freq[0].arefparam, 0);
|
|
for (f = 1; f < AMC_FREQUENCY_SLOTS; f++)
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_AREFPARAM_FREQ(f), amc_params.freq[f].arefparam, 0);
|
|
|
|
#if !SUPPORT_FPGA
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_ODTS, amc_params.odts | 0x00010000, 0);
|
|
#else
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_ODTS, amc_params.odts, 0);
|
|
#endif
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_LONGSR, 0x01000000 | amc_params.longsrcnt | amc_params.srextrarefcnt, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_AREFEN_FREQ(3), 0, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_AREFEN_FREQ(2), 0, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_AREFEN_FREQ(1), amc_params.aref_freq1, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_AREFEN_FREQ(0), 0x01011001 | amc_params.aref_freq0, 0);
|
|
// INITCMDCH0
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_CH0INITCMD, 0x1000, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, ((addr_t) &rAMC_CH0INITCMD) | RECONFIG_RAM_CMD_READ, 0, 0x1000);
|
|
|
|
/* Step 4: DRAM Reset, skipped for resume boot */
|
|
|
|
/* Step 5: Topology-specific configuration */
|
|
|
|
// ZQC
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_ZQC, 0x00090000, 0);
|
|
// MR10: ZQCL
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_CH0MRCMD, 0xab000a01, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, ((addr_t) &rAMC_CH01MRSTATUS) | RECONFIG_RAM_CMD_READ, 0, 1);
|
|
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_ZQC, 0x00080000, 0);
|
|
// ADDRCFG
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_ADDRCFG, amc_params.addrcfg, 0);
|
|
// CHNLDEC
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_AIU_CHNLDEC, amc_params.chnldec, 0);
|
|
|
|
/* Step 6: Switch from boot-clock speed to normal operation speed */
|
|
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_SCHEN, amc_params.schen_default | 0x1, 0);
|
|
|
|
/* Step 7: CA and Rddq calibration, skipped for resume boot */
|
|
|
|
/* Step 8: Enable other features */
|
|
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_AREFPARAM, amc_params.freq[0].arefparam | 0x00001800, 0);
|
|
// ZQC
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_ZQC, 0x010c03ff, 0);
|
|
// QBREN
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_QBREN, 0x00110001, 0);
|
|
// PSQWQCTRL0
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_PSQWQCTL0, 0x00010100, 0);
|
|
|
|
/* Step 9: Enable the Fast Critical Word Forwarding feature */
|
|
|
|
// RD_CWF
|
|
#if !SUPPORT_FPGA
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_AIUPRT_RD_CWF, 0x00323200, 0);
|
|
#else
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_AIUPRT_RD_CWF, 0, 0);
|
|
#endif
|
|
// QBRPARAM
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_QBRPARAM, 0x00510000, 0);
|
|
// QBREN
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_QBREN, 0x00111001, 0);
|
|
|
|
/* Step 10: Rddq and Wrdq offsets, restore dllupdtintvl POR value */
|
|
|
|
#if !SUPPORT_FPGA
|
|
/* Rddq calibration offsets */
|
|
|
|
for (byte = 0; byte < DQ_NUM_BYTES; byte++) {
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_DQSDLLCTRL_RD(0, byte), (1 << 24) | rAMP_DQSDLLCTRL_RD(0, byte), 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, ((addr_t) &rAMP_DQSDLLCTRL_RD(0, byte)) | RECONFIG_RAM_CMD_READ, 0, (1 << 24));
|
|
|
|
for (bit = 0; bit < DQ_NUM_BITS_PER_BYTE; bit++)
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_RDDQDESKEW_CTRL(0, byte, bit), rAMP_RDDQDESKEW_CTRL(0, byte, bit), 0);
|
|
}
|
|
|
|
/* Wrdq calibration offsets */
|
|
|
|
for (byte = 0; byte < DQ_NUM_BYTES; byte++) {
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_DQSDLLCTRL_WR(0, byte), (1 << 24) | rAMP_DQSDLLCTRL_WR(0, byte), 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, ((addr_t) &rAMP_DQSDLLCTRL_WR(0, byte)) | RECONFIG_RAM_CMD_READ, 0, (1 << 24));
|
|
|
|
// rAMP_DQWRLVLDLYCHAINCTRL.WrLvlClk90Dly already restored as part of wrlvl offset restorations
|
|
|
|
for (bit = 0; bit < DQ_NUM_BITS_PER_BYTE; bit++)
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_WRDQDESKEW_CTRL(0, byte, bit), rAMP_WRDQDESKEW_CTRL(0, byte, bit), 0);
|
|
|
|
// DM controlled by DQS register
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_WRDQSDESKEW_CTRL(0, byte), rAMP_WRDQSDESKEW_CTRL(0, byte), 0);
|
|
|
|
// DQS controlled by DM register
|
|
uint32_t dqs_deskew = rAMP_WRDMDESKEW_CTRL(0, byte);
|
|
// skip if 0, since that is reset value
|
|
if (dqs_deskew)
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_WRDMDESKEW_CTRL(0, byte), dqs_deskew, 0);
|
|
}
|
|
|
|
// DLLUPDTCMD
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_DLLUPDTCMD(AMP_CA,0), 0x00000001, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_DLLUPDTCMD(AMP_DQ,0), 0x00000001, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, ((addr_t) &rAMP_DLLUPDTCMD(AMP_CA,0)) | RECONFIG_RAM_CMD_READ, 0, 1);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, ((addr_t) &rAMP_DLLUPDTCMD(AMP_DQ,0)) | RECONFIG_RAM_CMD_READ, 0, 1);
|
|
#endif
|
|
|
|
// DLLUPDTINTVL
|
|
#if !SUPPORT_FPGA
|
|
dllupdtintvl = 0x1020005a;
|
|
#else
|
|
dllupdtintvl = 0;
|
|
#endif
|
|
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_DLLUPDTINTVL(AMP_CA,0), dllupdtintvl, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_DLLUPDTINTVL(AMP_DQ,0), dllupdtintvl, 0);
|
|
|
|
/* Step 11: Enable Power & ClockGating features */
|
|
|
|
// AMPCLK
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_AMPCLK(AMP_CA,0), 0x00010000, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMP_AMPCLK(AMP_DQ,0), 0x00010000, 0);
|
|
#if SUPPORT_FPGA
|
|
// PWRMNGTEN
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_PWRMNGTEN, 0x00110010, 0);
|
|
#else
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_PWRMNGTEN, 0x00111011, 0);
|
|
#endif
|
|
#if !SUPPORT_FPGA
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_PWRMNGTPARAM, amc_params.pwrmngtparam_guided, 0);
|
|
// PSQWQCTL1
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_PSQWQCTL1, 0x00000120, 0);
|
|
#endif
|
|
|
|
/* Step 12: Do a ODTS Read */
|
|
|
|
// MR4
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) &rAMC_CH0MRCMD, 0x00000411, 0);
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, ((addr_t) &rAMC_CH01MRSTATUS) | RECONFIG_RAM_CMD_READ, 0, 1);
|
|
|
|
/* AMC Tunables */
|
|
for (i = 0; i < sizeof(amc_tunables) / sizeof(amc_tunables[0]); i++) {
|
|
if (amc_tunables[i].reg == 0)
|
|
break;
|
|
reconfig_append_command(RECONFIG_TYPE_MEM, (addr_t) amc_tunables[i].reg, amc_tunables[i].value, 0);
|
|
}
|
|
|
|
}
|
|
|
|
#endif // WITH_HW_RECONFIG
|