/* * 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 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 // 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 // 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