first and last commit

This commit is contained in:
Chris Nutter committed 2023-07-08 13:03:17 -07:00
commit 1bf4efd552
2612 files changed
+636500

No files matched your search

+921
View File
@@ -0,0 +1,921 @@
/*
* Copyright (C) 2013-2015 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/dcs/dcs.h>
#include <drivers/dcs/dcs_regs.h>
#include <drivers/dcs/dcs_init_lib.h>
#include <drivers/dram.h>
#include <drivers/miu.h>
#include <drivers/reconfig.h>
#include <sys.h>
#include <platform/soc/hwclocks.h>
int mcu_initialize_dram (bool resume)
{
dcs_boottype_t boot_type;
// Don't perform DRAM initializion if the memory controller is already
// initialized (e.g., for SecureROM validation testing).
#if SUB_PLATFORM_S8000 || SUB_PLATFORM_S8003
if (resume || DCS_REG_READ_CH(0, rDCS_MCU_AMCCTRL) == 0) {
#endif
clock_gate(CLK_DCS0, true);
clock_gate(CLK_DCS1, true);
clock_gate(CLK_DCS2, true);
clock_gate(CLK_DCS3, true);
#if SUB_PLATFORM_S8001 && DCS_NUM_CHANNELS > 4
clock_gate(CLK_DCS4, true);
clock_gate(CLK_DCS5, true);
clock_gate(CLK_DCS6, true);
clock_gate(CLK_DCS7, true);
#endif
clock_gate(CLK_MCC, true);
boot_type = (resume)? DCS_BOOT_RESUME:DCS_BOOT_COLDBOOT;
// NOTE: Boot types AOP_DDR or AOP_AWAKE do not use this Code
// For those cases, the Init sequence is executed by the AOP
// Perform the LPDDR4 Init for this type of Boot
dcs_init(boot_type);
// <rdar://problem/18602531> Maui A1: Samsung 25nm LP4 RBM failures - WA
// Can't do this as part of dcs_dram_workarounds because reg value gets overwritten later in the sequence
const struct dcs_memory_device_info *dev_info = dcs_get_memory_device_info();
if(dev_info->vendor_id == JEDEC_LPDDR4_MANUF_ID_SAMSUNG)
if(dev_info->rev_id == 0x3 && dev_info->rev_id2 == 0x0)
for(uint32_t channel = 0; channel < DCS_NUM_CHANNELS; channel++)
DCS_REG_ACCESS(rDCS_MCU_AREFEN_FREQ(0) + (channel * DCS_SPACING)) = 0x1010013f;
#if SUB_PLATFORM_S8000 || SUB_PLATFORM_S8003
}
#endif
return 0;
}
void dcs_lock_down_mcc(void)
{
// Don't allow MCC as RAM
rAMCC_MCCGEN &= ~AMCC_MCCGEN_MCC_RAM_EN;
rAMCC_MCCGEN |= AMCC_MCCGEN_MCC_RAM_EN_LOCK;
// Don't allow tag RAM reads
rAMCC_MCCCFG_TAG_RD_DIS |= 1;
#if NUM_AMCCS > 1
rAMCC1_MCCGEN &= ~AMCC_MCCGEN_MCC_RAM_EN;
rAMCC1_MCCGEN |= AMCC_MCCGEN_MCC_RAM_EN_LOCK;
rAMCC1_MCCCFG_TAG_RD_DIS |= 1;
#endif
}
void mcu_bypass_prep (int step)
{
}
uint64_t mcu_get_memory_size (void)
{
return dcs_get_memory_size();
}
//================================================================================
void dcs_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
}
}
//================================================================================
// https://seg-docs.ecs.apple.com/projects/malta//release/UserManual/Hx_LPDDR4_RevID_Workaround.pdf
void dcs_dram_workarounds(dcs_boottype_t boot_type)
{
#if SUB_PLATFORM_S8000 || SUB_PLATFORM_S8003
uint32_t autoref_freq1;
#endif
#if SUB_PLATFORM_S8000
uint32_t dqvref_freq1;
#endif
if(boot_type == DCS_BOOT_COLDBOOT) {
const struct dcs_memory_device_info *dev_info = dcs_get_memory_device_info();
switch (dev_info->vendor_id) {
case JEDEC_LPDDR4_MANUF_ID_SAMSUNG:
#if SUB_PLATFORM_S8000 || SUB_PLATFORM_S8003
if(dev_info->rev_id == 5 && dev_info->rev_id2 == 1) {
// <rdar://problem/21042636> tRFCpbCyc_freq1 = 0x1c for Samsung
autoref_freq1 = DCS_REG_READ_CH(0, rDCS_MCU_AUTOREF_FREQ(1));
autoref_freq1 &= 0x00ffffff;
autoref_freq1 |= (0x1c << 24);
dcs_reg_write_all_chan(rDCS_MCU_AUTOREF_FREQ(1), autoref_freq1);
}
#endif
#if SUB_PLATFORM_S8000
if(dev_info->rev_id == 5) {
dqvref_freq1 = 0x00ec00ec; // Maui
dcs_reg_write_all_chan(rDCS_AMP_VREF_F(AMP_DQ0, 1), dqvref_freq1);
dcs_reg_write_all_chan(rDCS_AMP_VREF_F(AMP_DQ1, 1), dqvref_freq1);
}
#endif
break;
case JEDEC_LPDDR4_MANUF_ID_HYNIX:
#if SUB_PLATFORM_S8000 || SUB_PLATFORM_S8003
if(dev_info->rev_id == 3 && dev_info->rev_id2 == 2) {
// <rdar://problem/21042636> tRFCpbCyc_freq1 = 0x1c for Hynix
autoref_freq1 = DCS_REG_READ_CH(0, rDCS_MCU_AUTOREF_FREQ(1));
autoref_freq1 &= 0x00ffffff;
autoref_freq1 |= (0x1c << 24);
dcs_reg_write_all_chan(rDCS_MCU_AUTOREF_FREQ(1), autoref_freq1);
}
#endif
#if SUB_PLATFORM_S8000
if(dev_info->rev_id == 3) {
dqvref_freq1 = 0x00df00df; // Maui
dcs_reg_write_all_chan(rDCS_AMP_VREF_F(AMP_DQ0, 1), dqvref_freq1);
dcs_reg_write_all_chan(rDCS_AMP_VREF_F(AMP_DQ1, 1), dqvref_freq1);
}
#endif
// <rdar://problem/18183851> Workarounds: Pull Up/Down shift for Maui Hynix 25nm
if(dev_info->rev_id == 0x3) {
// Test MRS Exit
dcs_mrcmd(MR_WRITE, DCS_NUM_CHANNELS, DCS_NUM_RANKS, 0x9, 0x0);
// Test MRS Entry
dcs_mrcmd(MR_WRITE, DCS_NUM_CHANNELS, DCS_NUM_RANKS, 0x9, 0xb0);
dcs_mrcmd(MR_WRITE, DCS_NUM_CHANNELS, DCS_NUM_RANKS, 0x9, 0xe0);
dcs_mrcmd(MR_WRITE, DCS_NUM_CHANNELS, DCS_NUM_RANKS, 0x9, 0x90);
if(dev_info->rev_id2 == 0x0) {
// Rising Slew-rate up
dcs_mrcmd(MR_WRITE, DCS_NUM_CHANNELS, DCS_NUM_RANKS, 0x9, 0x87);
// Self-refresh OSC Min
dcs_mrcmd(MR_WRITE, DCS_NUM_CHANNELS, DCS_NUM_RANKS, 0x9, 0xd0);
dcs_mrcmd(MR_WRITE, DCS_NUM_CHANNELS, DCS_NUM_RANKS, 0x9, 0x90);
dcs_mrcmd(MR_WRITE, DCS_NUM_CHANNELS, DCS_NUM_RANKS, 0x9, 0x86);
dcs_mrcmd(MR_WRITE, DCS_NUM_CHANNELS, DCS_NUM_RANKS, 0x9, 0x81);
}
// For all SoCs that use this particular DRAM
if(dev_info->rev_id2 <= 0x1) {
// Pull Up RON shift
dcs_mrcmd(MR_WRITE, DCS_NUM_CHANNELS, DCS_NUM_RANKS, 0x9, 0xc4);
dcs_mrcmd(MR_WRITE, DCS_NUM_CHANNELS, DCS_NUM_RANKS, 0x9, 0x90);
dcs_mrcmd(MR_WRITE, DCS_NUM_CHANNELS, DCS_NUM_RANKS, 0x9, 0x8e);
dcs_mrcmd(MR_WRITE, DCS_NUM_CHANNELS, DCS_NUM_RANKS, 0x9, 0x81);
// Pull Down RON shift
dcs_mrcmd(MR_WRITE, DCS_NUM_CHANNELS, DCS_NUM_RANKS, 0x9, 0xc4);
dcs_mrcmd(MR_WRITE, DCS_NUM_CHANNELS, DCS_NUM_RANKS, 0x9, 0x94);
dcs_mrcmd(MR_WRITE, DCS_NUM_CHANNELS, DCS_NUM_RANKS, 0x9, 0x92);
dcs_mrcmd(MR_WRITE, DCS_NUM_CHANNELS, DCS_NUM_RANKS, 0x9, 0x81);
// ZQ calibration START MPC cmd
dcs_mrcmd(MR_MPC, DCS_NUM_CHANNELS, DCS_NUM_RANKS, 0x0, 0x4f);
// wait 1us for tZQCAL
dcs_spin(1, "Workarounds -- tZQCAL");
// ZQ calibration LATCH MPC cmd
dcs_mrcmd(MR_MPC, DCS_NUM_CHANNELS, DCS_NUM_RANKS, 0x0, 0x51);
}
}
break;
case JEDEC_LPDDR4_MANUF_ID_MICRON:
#if SUB_PLATFORM_S8000 || SUB_PLATFORM_S8003
if(dev_info->rev_id == 1 && dev_info->rev_id2 == 2) {
// <rdar://problem/21042636> tRFCpbCyc_freq1 = 0x20 for Micron
autoref_freq1 = DCS_REG_READ_CH(0, rDCS_MCU_AUTOREF_FREQ(1));
autoref_freq1 &= 0x00ffffff;
autoref_freq1 |= (0x20 << 24);
dcs_reg_write_all_chan(rDCS_MCU_AUTOREF_FREQ(1), autoref_freq1);
}
#endif
#if SUB_PLATFORM_S8000
if(dev_info->rev_id == 1) {
dqvref_freq1 = 0x00ea00ea; // Maui
dcs_reg_write_all_chan(rDCS_AMP_VREF_F(AMP_DQ0, 1), dqvref_freq1);
dcs_reg_write_all_chan(rDCS_AMP_VREF_F(AMP_DQ1, 1), dqvref_freq1);
}
#endif
if(dev_info->rev_id == 0x1) {
// Test MRS Exit
dcs_mrcmd(MR_WRITE, DCS_NUM_CHANNELS, DCS_NUM_RANKS, 0x9, 0x0);
// <rdar://problem/20303861> Test MRS: Disable VREFDQ TAP code local latch
dcs_mrcmd(MR_WRITE, DCS_NUM_CHANNELS, DCS_NUM_RANKS, 0x9, 0xf1);
dcs_mrcmd(MR_WRITE, DCS_NUM_CHANNELS, DCS_NUM_RANKS, 0x9, 0x40);
}
break;
default:
break;
}
}
}
#if SUB_PLATFORM_S8000 || SUB_PLATFORM_S8003
void dcs_dram_workarounds_step12 ( void )
{
const struct dcs_memory_device_info *dev_info = dcs_get_memory_device_info();
if ( (dev_info->vendor_id == JEDEC_LPDDR4_MANUF_ID_SAMSUNG) && (dev_info->rev_id == 5) && (dev_info->rev_id2 == 1) )
{
if((dcs_cfg.chipID == 0x8000 && dcs_cfg.chipRev >= CHIP_REVISION_C0) || (dcs_cfg.chipID == 0x8003 && dcs_cfg.chipRev >= CHIP_REVISION_A1) ||
(dcs_cfg.chipID == 0x8001 && dcs_cfg.chipRev >= CHIP_REVISION_B0) )
{
dcs_mrcmd(MR_WRITE, DCS_NUM_CHANNELS, DCS_NUM_RANKS, 0x0b, 0x34);
dcs_mrcmd(MR_MPC, DCS_NUM_CHANNELS, DCS_NUM_RANKS, 0x00, 0x4F);
dcs_spin(1, "Workaround-Samsung--step-12-tzQCAL");
dcs_mrcmd(MR_MPC, DCS_NUM_CHANNELS, DCS_NUM_RANKS, 0x00, 0x51);
dcs_spin(1, "Workaround-Samsung--step-12-tZQLAT");
dcs_reg_write_all_chan(rDCS_MCU_FREQCHNGCTL_FREQ(2, 0), 0xb303340b);
}
}
}
#endif
//================================================================================
// Grab (Platform Specific) Tables with Definitions of Values for DCS Init & DCS Tunables
#include <platform/dcsconfig.h>
#if DCS_FIXUP_PARAMS
// Grab (Target Specific) Definition of Required Fixups to the Values for DCS Init
#include <target/dcsfixup.h>
#endif
// use_dcs_params is already the same as dcs_params, unless we want to override with older chip-rev or target specific values
void dcs_init_config_params(dcs_config_params_t *use_dcs_params, dcs_target_t targtype)
{
#if SUB_PLATFORM_S8000
// Maui B0 DCS param table
if(platform_get_chip_revision() < CHIP_REVISION_C0)
memcpy(use_dcs_params, &dcs_params_b0, sizeof(dcs_config_params_t));
#endif
#if DCS_FIXUP_PARAMS
// This gives the particular target a chance to make target-specific changes
dcs_init_config_fixup_params(use_dcs_params, targtype);
#endif
}
const dcs_tunable_t *dcs_init_tunable_table(uint32_t *table_len)
{
const dcs_tunable_t *tunables = dcs_tunables;
uint32_t tunables_size = sizeof(dcs_tunables);
#if SUB_PLATFORM_S8000
// Maui B0 DCS tunables
if(platform_get_chip_revision() < CHIP_REVISION_C0) {
tunables = dcs_tunables_b0;
tunables_size = sizeof(dcs_tunables_b0);
}
#endif
if (table_len)
*table_len = tunables_size / sizeof(tunables[0]);
return tunables;
}
void dcs_aop_ddr_to_awake_post_tunables_insert(void)
{
uint32_t i, num_tunables = 0;
const dcs_tunable_t *tunables = NULL;
uintptr_t curr_reg = 0;
uint32_t reg_val = 0;
tunables = dcs_init_tunable_table(&num_tunables);
// At the time this function is called, tunables values are already expected to be programmed into the registers.
// Expected format of the dcs_tunables table: Each field that has a tunable value is 1 entry in the tunables table
for(i = 0; i < num_tunables; i++, tunables++) {
// end of table
if(tunables->reg == 0)
break;
// skip over subsequent tunables values for different fields in the same register, since we read out the entire register the first time
if(tunables->reg == curr_reg)
continue;
curr_reg = tunables->reg;
if(dcs_reg_is_outside_dcs_block(curr_reg)) {
reg_val = DCS_REG_ACCESS(curr_reg);
reconfig_command_write(AOP_DDR_AWAKE_POST, curr_reg, reg_val, false);
} else {
// if reg is within DCS hw block, the reg is duplicated for each instance of the hw block, just read out 1st instance
// and write that value for all instances
reg_val = DCS_REG_READ_CH(0, curr_reg);
for(uint32_t channel = 0; channel < DCS_NUM_CHANNELS; channel++)
reconfig_command_write(AOP_DDR_AWAKE_POST, (curr_reg + (channel * DCS_SPACING)), reg_val, false);
}
}
}
#if SUB_PLATFORM_S8000 || SUB_PLATFORM_S8003
//================================================================================
// Save off calibration results to AOP_SRAM region (later to be stitched into mcu_aop_awake_reconfig_restore sequence)
// Order of registers to be saved matches the order in the reconfig sequence
volatile uint32_t *dcs_save_calibration_results(volatile uint32_t *save_region, uint32_t freq)
{
uint32_t ch, n;
// Registers to be saved off after calibration in freq 1 has completed
if (freq == DCS_FREQ(1)) {
// CASDLLCTRL
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++)
*save_region++ = DCS_REG_ACCESS(rAMP_CASDLLCTRL(ch));
// CSSDLLCTRL
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++)
*save_region++ = DCS_REG_ACCESS(rAMP_CSSDLLCTRL(ch));
// CKSDLLCTRL
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++)
*save_region++ = DCS_REG_ACCESS(rAMP_CKSDLLCTRL(ch));
// AMPCAWRLVLSDLLCODE
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++)
*save_region++ = DCS_REG_ACCESS(rAMP_CAWRLVLSDLLCODE(ch));
// CA_DESKEW_CTRL
for(n = 0; n < CA_NUM_BITS; n++)
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++)
*save_region++ = DCS_REG_ACCESS(rAMP_CADESKEW_CTRL(ch, n));
// CS_DESKEW_CTRL
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++)
*save_region++ = DCS_REG_ACCESS(rAMP_CSDESKEW_CTRL(ch));
// CK_DESKEW_CTRL
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++)
*save_region++ = DCS_REG_ACCESS(rAMP_CKDESKEW_CTRL(ch));
// AMPWRLVLSDLLCODE0
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++) {
*save_region++ = DCS_REG_ACCESS(rAMP_DQWRLVLSDLLCODE(0, ch));
*save_region++ = DCS_REG_ACCESS(rAMP_DQWRLVLSDLLCODE(1, ch));
}
// VREF_Fx
for(n = 0; n < DCS_FREQUENCY_SLOTS; n++) {
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++) {
*save_region++ = DCS_REG_READ_CH(ch, rDCS_AMP_VREF_F(AMP_DQ0, n));
*save_region++ = DCS_REG_READ_CH(ch, rDCS_AMP_VREF_F(AMP_DQ1, n));
}
}
// AUTOREF_FREQ1
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++)
*save_region++ = DCS_REG_READ_CH(ch, rDCS_MCU_AUTOREF_FREQ(1));
// CAMDLLVTSCALEREFCONTROL
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++) {
*save_region++ = DCS_REG_READ_CH(ch, rDCS_AMP_CAMDLL_VTSCALE_REFCNTL(AMP_DQ0));
*save_region++ = DCS_REG_READ_CH(ch, rDCS_AMP_CAMDLL_VTSCALE_REFCNTL(AMP_DQ1));
}
// RDMDLLVTSCALEREFCONTROL
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++) {
*save_region++ = DCS_REG_READ_CH(ch, rDCS_AMP_RDMDLL_VTSCALE_REFCNTL(AMP_DQ0));
*save_region++ = DCS_REG_READ_CH(ch, rDCS_AMP_RDMDLL_VTSCALE_REFCNTL(AMP_DQ1));
}
// WRMDLLVTSCALEREFCONTROL
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++) {
*save_region++ = DCS_REG_READ_CH(ch, rDCS_AMP_WRMDLL_VTSCALE_REFCNTL(AMP_DQ0));
*save_region++ = DCS_REG_READ_CH(ch, rDCS_AMP_WRMDLL_VTSCALE_REFCNTL(AMP_DQ1));
}
// FREQCHNGCTL1_FREQ1
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++)
*save_region++ = DCS_REG_READ_CH(ch, rDCS_MCU_FREQCHNGCTL_FREQ(1, 1));
} else if (freq == DCS_FREQ(0)) {
// Registers to be saved off after calibration in freq 0 has completed
// VREF_F0
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++) {
*save_region++ = DCS_REG_READ_CH(ch, rDCS_AMP_VREF_F(AMP_DQ0, 0));
*save_region++ = DCS_REG_READ_CH(ch, rDCS_AMP_VREF_F(AMP_DQ1, 0));
}
// FREQCHNGCTL1_FREQ0
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++)
*save_region++ = DCS_REG_READ_CH(ch, rDCS_MCU_FREQCHNGCTL_FREQ(1, 0));
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++)
*save_region++ = DCS_REG_READ_CH(ch, rDCS_MCU_FREQCHNGCTL_FREQ(2, 0));
} else if (freq == 0) {
// <rdar://problem/23355941> Maui/Malta: Samsung DRAM workaround: disable hw zqcal
// rGLBTIMER_ZQCTIMER
*save_region++ = DCS_REG_ACCESS(rGLBTIMER_ZQCTIMER);
}
return save_region;
}
//================================================================================
// Stitch the saved calibration results into the reconfig sequence
// To be called immediately after stitching mcu_aop_awake_reconfig_pre_restore
// Uses mcu_aop_awake_reconfig_restore as reference for register order and fields
void dcs_restore_calibration_results(volatile uint32_t *save_region)
{
uint32_t ch, n, f;
uint32_t reg_val;
// CASDLLCTRL
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++) {
reg_val = ((*save_region) & SDLLOVRVAL_MASK) | RUNSDLLUPDWRRESULT;
reconfig_command_write(AOP_DDR_AWAKE_POST, rAMP_CASDLLCTRL(ch), reg_val, false);
save_region++;
}
// CSSDLLCTRL
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++) {
reg_val = ((*save_region) & SDLLOVRVAL_MASK) | RUNSDLLUPDWRRESULT;
reconfig_command_write(AOP_DDR_AWAKE_POST, rAMP_CSSDLLCTRL(ch), reg_val, false);
save_region++;
}
// CKSDLLCTRL
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++) {
reg_val = ((*save_region) & SDLLOVRVAL_MASK) | RUNSDLLUPDWRRESULT;
reconfig_command_write(AOP_DDR_AWAKE_POST, rAMP_CKSDLLCTRL(ch), reg_val, false);
save_region++;
}
// AMPCAWRLVLSDLLCODE
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++) {
reg_val = ((*save_region) & WRLVLSDLLCODE_MASK) | WRLVLRUNUPDWRRESULT;
reconfig_command_write(AOP_DDR_AWAKE_POST, rAMP_CAWRLVLSDLLCODE(ch), reg_val, false);
save_region++;
}
// Poll for AMPCAWRLVLSDLLCODE.WRLVLRUNUPDWRRESULT to clear
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++)
reconfig_command_read(AOP_DDR_AWAKE_POST, rAMP_CAWRLVLSDLLCODE(ch), 0, WRLVLRUNUPDWRRESULT, 0, false);
// CA_DESKEW_CTRL
for(n = 0; n < CA_NUM_BITS; n++) {
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++) {
reg_val = ((*save_region) & DESKEWCODE_MASK) | RUNDESKEWUPD;
reconfig_command_write(AOP_DDR_AWAKE_POST, rAMP_CADESKEW_CTRL(ch, n), reg_val, false);
save_region++;
}
}
// CS_DESKEW_CTRL
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++) {
reg_val = ((*save_region) & DESKEWCODE_MASK) | RUNDESKEWUPD;
reconfig_command_write(AOP_DDR_AWAKE_POST, rAMP_CSDESKEW_CTRL(ch), reg_val, false);
save_region++;
}
// CK_DESKEW_CTRL
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++) {
reg_val = ((*save_region) & DESKEWCODE_MASK) | RUNDESKEWUPD;
reconfig_command_write(AOP_DDR_AWAKE_POST, rAMP_CKDESKEW_CTRL(ch), reg_val, false);
save_region++;
}
// AMPWRLVLSDLLCODE0
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++) {
// for DQ0 and DQ1
for(n = 0; n < 2; n++) {
reg_val = ((*save_region) & WRLVLSDLLCODE_MASK) | WRLVLRUNUPDWRRESULT;
reconfig_command_write(AOP_DDR_AWAKE_POST, rAMP_DQWRLVLSDLLCODE(n, ch), reg_val, false);
save_region++;
}
}
// VREF_Fx
for(f = 0; f < DCS_FREQUENCY_SLOTS; f++) {
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++) {
// for DQ0 and DQ1
for(n = AMP_DQ0; n < DCS_AMP_NUM_PHYS; n++) {
reg_val = (*save_region) & (VREFSEL_MASK | DQSVREFSEL_MASK);
reconfig_command_write(AOP_DDR_AWAKE_POST, rDCS_AMP_VREF_F(n, f) + (ch * DCS_SPACING), reg_val, false);
save_region++;
}
}
}
// AUTOREF_FREQ1
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++) {
reg_val = *save_region;
reconfig_command_write(AOP_DDR_AWAKE_POST, rDCS_MCU_AUTOREF_FREQ(1) + (ch * DCS_SPACING), reg_val, false);
save_region++;
}
// CAMDLLVTSCALEREFCONTROL
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++) {
// for DQ0 and DQ1: shift the status field value into the override field
for(n = AMP_DQ0; n < DCS_AMP_NUM_PHYS; n++) {
reg_val = (((*save_region) & VTSCALEREFSTATUS_MASK) << VTSCALEREFOVERRIDEVAL_SHIFT) | VTSCALEREFUPDATE;
reconfig_command_write(AOP_DDR_AWAKE_POST, rDCS_AMP_CAMDLL_VTSCALE_REFCNTL(n) + (ch * DCS_SPACING), reg_val, false);
save_region++;
}
}
// RDMDLLVTSCALEREFCONTROL
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++) {
// for DQ0 and DQ1: shift the status field value into the override field
for(n = AMP_DQ0; n < DCS_AMP_NUM_PHYS; n++) {
reg_val = (((*save_region) & VTSCALEREFSTATUS_MASK) << VTSCALEREFOVERRIDEVAL_SHIFT) | VTSCALEREFUPDATE;
reconfig_command_write(AOP_DDR_AWAKE_POST, rDCS_AMP_RDMDLL_VTSCALE_REFCNTL(n) + (ch * DCS_SPACING), reg_val, false);
save_region++;
}
}
// WRMDLLVTSCALEREFCONTROL
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++) {
// for DQ0 and DQ1: shift the status field value into the override field
for(n = AMP_DQ0; n < DCS_AMP_NUM_PHYS; n++) {
reg_val = (((*save_region) & VTSCALEREFSTATUS_MASK) << VTSCALEREFOVERRIDEVAL_SHIFT) | VTSCALEREFUPDATE;
reconfig_command_write(AOP_DDR_AWAKE_POST, rDCS_AMP_WRMDLL_VTSCALE_REFCNTL(n) + (ch * DCS_SPACING), reg_val, false);
save_region++;
}
}
// FREQCHNGCTL1_FREQ1
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++) {
reg_val = *save_region;
reconfig_command_write(AOP_DDR_AWAKE_POST, rDCS_MCU_FREQCHNGCTL_FREQ(1, 1) + (ch * DCS_SPACING), reg_val, false);
save_region++;
}
// The next set of registers were saved off after freq0 calibration completed
// VREF_F0
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++) {
reg_val = *save_region;
reconfig_command_write(AOP_DDR_AWAKE_POST, rDCS_AMP_VREF_F(AMP_DQ0, 0) + (ch * DCS_SPACING), reg_val, false);
save_region++;
reg_val = *save_region;
reconfig_command_write(AOP_DDR_AWAKE_POST, rDCS_AMP_VREF_F(AMP_DQ1, 0) + (ch * DCS_SPACING), reg_val, false);
save_region++;
}
// FREQCHNGCTL1_FREQ0
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++) {
reg_val = *save_region;
reconfig_command_write(AOP_DDR_AWAKE_POST, rDCS_MCU_FREQCHNGCTL_FREQ(1, 0) + (ch * DCS_SPACING), reg_val, false);
save_region++;
}
// FREQCHNGCTL2_FREQ0
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++) {
reg_val = *save_region;
reconfig_command_write(AOP_DDR_AWAKE_POST, rDCS_MCU_FREQCHNGCTL_FREQ(2, 0) + (ch * DCS_SPACING), reg_val, false);
save_region++;
}
// <rdar://problem/23355941> Maui/Malta: Samsung DRAM workaround: disable hw zqcal
// rGLBTIMER_ZQCTIMER
reg_val = *save_region;
reconfig_command_write(AOP_DDR_AWAKE_POST, rGLBTIMER_ZQCTIMER, reg_val, false);
save_region++;
}
#endif // #if SUB_PLATFORM_S8000 || SUB_PLATFORM_S8003
#if SUB_PLATFORM_S8001
//================================================================================
// Save off calibration results to AOP_SRAM region (later to be stitched into mcu_aop_awake_reconfig_restore sequence)
// Order of registers to be saved matches the order in the reconfig sequence
volatile uint32_t *dcs_save_calibration_results(volatile uint32_t *save_region, uint32_t freq)
{
uint32_t ch, n;
if(freq == DCS_FREQ(0)) {
// CASDLLCTRL
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++)
*save_region++ = DCS_REG_ACCESS(rAMP_CASDLLCTRL(ch));
// CSSDLLCTRL
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++)
*save_region++ = DCS_REG_ACCESS(rAMP_CSSDLLCTRL(ch));
// CKSDLLCTRL
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++)
*save_region++ = DCS_REG_ACCESS(rAMP_CKSDLLCTRL(ch));
// AMPCAWRLVLSDLLCODE
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++)
*save_region++ = DCS_REG_ACCESS(rAMP_CAWRLVLSDLLCODE(ch));
// CA_DESKEW_CTRL
for(n = 0; n < CA_NUM_BITS; n++)
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++)
*save_region++ = DCS_REG_ACCESS(rAMP_CADESKEW_CTRL(ch, n));
// CS_DESKEW_CTRL
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++)
*save_region++ = DCS_REG_ACCESS(rAMP_CSDESKEW_CTRL(ch));
// CK_DESKEW_CTRL
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++)
*save_region++ = DCS_REG_ACCESS(rAMP_CKDESKEW_CTRL(ch));
// AMPWRLVLSDLLCODE0
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++) {
*save_region++ = DCS_REG_ACCESS(rAMP_DQWRLVLSDLLCODE(0, ch));
*save_region++ = DCS_REG_ACCESS(rAMP_DQWRLVLSDLLCODE(1, ch));
}
// VREF_Fx
for(n = 0; n < DCS_FREQUENCY_SLOTS; n++) {
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++) {
*save_region++ = DCS_REG_READ_CH(ch, rDCS_AMP_VREF_F(AMP_DQ0, n));
*save_region++ = DCS_REG_READ_CH(ch, rDCS_AMP_VREF_F(AMP_DQ1, n));
}
}
// WRDQCALVREFCODESTATUS
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++)
*save_region++ = DCS_REG_READ_CH(ch, rDCS_AMP_WRDQCALVREFCODESTATUS);
// RDDQCALVREFCODESTATUS
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++)
*save_region++ = DCS_REG_READ_CH(ch, rDCS_AMP_RDDQCALVREFCODESTATUS);
// CAMDLLVTSCALEREFCONTROL
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++) {
*save_region++ = DCS_REG_READ_CH(ch, rDCS_AMP_CAMDLL_VTSCALE_REFCNTL(AMP_DQ0));
*save_region++ = DCS_REG_READ_CH(ch, rDCS_AMP_CAMDLL_VTSCALE_REFCNTL(AMP_DQ1));
}
// RDMDLLVTSCALEREFCONTROL
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++) {
*save_region++ = DCS_REG_READ_CH(ch, rDCS_AMP_RDMDLL_VTSCALE_REFCNTL(AMP_DQ0));
*save_region++ = DCS_REG_READ_CH(ch, rDCS_AMP_RDMDLL_VTSCALE_REFCNTL(AMP_DQ1));
}
// WRMDLLVTSCALEREFCONTROL
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++) {
*save_region++ = DCS_REG_READ_CH(ch, rDCS_AMP_WRMDLL_VTSCALE_REFCNTL(AMP_DQ0));
*save_region++ = DCS_REG_READ_CH(ch, rDCS_AMP_WRMDLL_VTSCALE_REFCNTL(AMP_DQ1));
}
// FREQCHNGCTL1_FREQ0
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++)
*save_region++ = DCS_REG_READ_CH(ch, rDCS_MCU_FREQCHNGCTL_FREQ(1, 0));
// FREQCHNGCTL2_FREQ0
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++)
*save_region++ = DCS_REG_READ_CH(ch, rDCS_MCU_FREQCHNGCTL_FREQ(2, 0));
// FREQCHNGCTL2_FREQ3
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++)
*save_region++ = DCS_REG_READ_CH(ch, rDCS_MCU_FREQCHNGCTL_FREQ(2, 3));
// FREQCHNGCTL4_FREQ0
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++)
*save_region++ = DCS_REG_READ_CH(ch, rDCS_MCU_FREQCHNGCTL_FREQ(4, 0));
// CB_IMPCTL
*save_region++ = DCS_REG_READ_CH(0, rDCS_AMPH_CB_IMPCTL);
// B0_ODT
*save_region++ = DCS_REG_READ_CH(0, rDCS_AMPH_B0_ODT);
// B1_ODT
*save_region++ = DCS_REG_READ_CH(0, rDCS_AMPH_B1_ODT);
// DQS0_ODT
*save_region++ = DCS_REG_READ_CH(0, rDCS_AMPH_DQS0_ODT);
// DQS1_ODT
*save_region++ = DCS_REG_READ_CH(0, rDCS_AMPH_DQS1_ODT);
} else if(freq == 0) {
// <rdar://problem/23244578> Elba: Samsung DRAM workaround: disable hw zqcal
// rGLBTIMER_ZQCTIMER
*save_region++ = DCS_REG_ACCESS(rGLBTIMER_ZQCTIMER);
}
return save_region;
}
//================================================================================
// Stitch the saved calibration results into the reconfig sequence
// To be called immediately after stitching mcu_aop_awake_reconfig_pre_restore
// Uses mcu_aop_awake_reconfig_restore as reference for register order and fields
void dcs_restore_calibration_results(volatile uint32_t *save_region)
{
uint32_t ch, n, f;
uint32_t reg_val;
// CASDLLCTRL
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++) {
reg_val = ((*save_region) & SDLLOVRVAL_MASK) | RUNSDLLUPDWRRESULT;
reconfig_command_write(AOP_DDR_AWAKE_POST, rAMP_CASDLLCTRL(ch), reg_val, false);
save_region++;
}
// CSSDLLCTRL
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++) {
reg_val = ((*save_region) & SDLLOVRVAL_MASK) | RUNSDLLUPDWRRESULT;
reconfig_command_write(AOP_DDR_AWAKE_POST, rAMP_CSSDLLCTRL(ch), reg_val, false);
save_region++;
}
// CKSDLLCTRL
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++) {
reg_val = ((*save_region) & SDLLOVRVAL_MASK) | RUNSDLLUPDWRRESULT;
reconfig_command_write(AOP_DDR_AWAKE_POST, rAMP_CKSDLLCTRL(ch), reg_val, false);
save_region++;
}
// AMPCAWRLVLSDLLCODE
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++) {
reg_val = ((*save_region) & WRLVLSDLLCODE_MASK) | WRLVLRUNUPDWRRESULT;
reconfig_command_write(AOP_DDR_AWAKE_POST, rAMP_CAWRLVLSDLLCODE(ch), reg_val, false);
save_region++;
}
// Poll for AMPCAWRLVLSDLLCODE.WRLVLRUNUPDWRRESULT to clear
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++)
reconfig_command_read(AOP_DDR_AWAKE_POST, rAMP_CAWRLVLSDLLCODE(ch), 0, WRLVLRUNUPDWRRESULT, 0, false);
// CA_DESKEW_CTRL
for(n = 0; n < CA_NUM_BITS; n++) {
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++) {
reg_val = ((*save_region) & DESKEWCODE_MASK) | RUNDESKEWUPD;
reconfig_command_write(AOP_DDR_AWAKE_POST, rAMP_CADESKEW_CTRL(ch, n), reg_val, false);
save_region++;
}
}
// CS_DESKEW_CTRL
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++) {
reg_val = ((*save_region) & DESKEWCODE_MASK) | RUNDESKEWUPD;
reconfig_command_write(AOP_DDR_AWAKE_POST, rAMP_CSDESKEW_CTRL(ch), reg_val, false);
save_region++;
}
// CK_DESKEW_CTRL
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++) {
reg_val = ((*save_region) & DESKEWCODE_MASK) | RUNDESKEWUPD;
reconfig_command_write(AOP_DDR_AWAKE_POST, rAMP_CKDESKEW_CTRL(ch), reg_val, false);
save_region++;
}
// AMPWRLVLSDLLCODE0
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++) {
// for DQ0 and DQ1
for(n = 0; n < 2; n++) {
reg_val = ((*save_region) & WRLVLSDLLCODE_MASK) | WRLVLRUNUPDWRRESULT;
reconfig_command_write(AOP_DDR_AWAKE_POST, rAMP_DQWRLVLSDLLCODE(n, ch), reg_val, false);
save_region++;
}
}
// VREF_Fx
for(f = 0; f < DCS_FREQUENCY_SLOTS; f++) {
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++) {
// for DQ0 and DQ1
for(n = AMP_DQ0; n < DCS_AMP_NUM_PHYS; n++) {
reg_val = (*save_region) & (VREFSEL_MASK | DQSVREFSEL_MASK);
reconfig_command_write(AOP_DDR_AWAKE_POST, rDCS_AMP_VREF_F(n, f) + (ch * DCS_SPACING), reg_val, false);
save_region++;
}
}
}
// WRDQCALVREFCODECONTROL
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++) {
reg_val = (*save_region);
reconfig_command_write(AOP_DDR_AWAKE_POST, rDCS_AMP_WRDQCALVREFCODECONTROL + (ch * DCS_SPACING), reg_val, false);
save_region++;
}
// RDDQCALVREFCODECONTROL
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++) {
reg_val = (*save_region);
reconfig_command_write(AOP_DDR_AWAKE_POST, rDCS_AMP_RDDQCALVREFCODECONTROL + (ch * DCS_SPACING), reg_val, false);
save_region++;
}
// CAMDLLVTSCALEREFCONTROL
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++) {
// for DQ0 and DQ1: shift the status field value into the override field
for(n = AMP_DQ0; n < DCS_AMP_NUM_PHYS; n++) {
reg_val = (((*save_region) & VTSCALEREFSTATUS_MASK) << VTSCALEREFOVERRIDEVAL_SHIFT) | VTSCALEREFUPDATE;
reconfig_command_write(AOP_DDR_AWAKE_POST, rDCS_AMP_CAMDLL_VTSCALE_REFCNTL(n) + (ch * DCS_SPACING), reg_val, false);
save_region++;
}
}
// RDMDLLVTSCALEREFCONTROL
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++) {
// for DQ0 and DQ1: shift the status field value into the override field
for(n = AMP_DQ0; n < DCS_AMP_NUM_PHYS; n++) {
reg_val = (((*save_region) & VTSCALEREFSTATUS_MASK) << VTSCALEREFOVERRIDEVAL_SHIFT) | VTSCALEREFUPDATE;
reconfig_command_write(AOP_DDR_AWAKE_POST, rDCS_AMP_RDMDLL_VTSCALE_REFCNTL(n) + (ch * DCS_SPACING), reg_val, false);
save_region++;
}
}
// WRMDLLVTSCALEREFCONTROL
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++) {
// for DQ0 and DQ1: shift the status field value into the override field
for(n = AMP_DQ0; n < DCS_AMP_NUM_PHYS; n++) {
reg_val = (((*save_region) & VTSCALEREFSTATUS_MASK) << VTSCALEREFOVERRIDEVAL_SHIFT) | VTSCALEREFUPDATE;
reconfig_command_write(AOP_DDR_AWAKE_POST, rDCS_AMP_WRMDLL_VTSCALE_REFCNTL(n) + (ch * DCS_SPACING), reg_val, false);
save_region++;
}
}
// FREQCHNGCTL1_FREQ0
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++) {
reg_val = *save_region;
reconfig_command_write(AOP_DDR_AWAKE_POST, rDCS_MCU_FREQCHNGCTL_FREQ(1, 0) + (ch * DCS_SPACING), reg_val, false);
save_region++;
}
// FREQCHNGCTL2_FREQ0
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++) {
reg_val = *save_region;
reconfig_command_write(AOP_DDR_AWAKE_POST, rDCS_MCU_FREQCHNGCTL_FREQ(2, 0) + (ch * DCS_SPACING), reg_val, false);
save_region++;
}
// FREQCHNGCTL2_FREQ3
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++) {
reg_val = *save_region;
reconfig_command_write(AOP_DDR_AWAKE_POST, rDCS_MCU_FREQCHNGCTL_FREQ(2, 3) + (ch * DCS_SPACING), reg_val, false);
save_region++;
}
// <rdar://problem/23244578> Elba: Samsung DRAM workaround: disable hw zqcal
// FREQCHNGCTL4_FREQ0
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++) {
reg_val = *save_region;
reconfig_command_write(AOP_DDR_AWAKE_POST, rDCS_MCU_FREQCHNGCTL_FREQ(4, 0) + (ch * DCS_SPACING), reg_val, false);
save_region++;
}
// CB_IMPCTL
reg_val = *save_region;
save_region++;
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++)
reconfig_command_write(AOP_DDR_AWAKE_POST, rDCS_AMPH_CB_IMPCTL + (ch * DCS_SPACING), reg_val, false);
// B0_ODT
reg_val = *save_region;
save_region++;
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++)
reconfig_command_write(AOP_DDR_AWAKE_POST, rDCS_AMPH_B0_ODT + (ch * DCS_SPACING), reg_val, false);
// B1_ODT
reg_val = *save_region;
save_region++;
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++)
reconfig_command_write(AOP_DDR_AWAKE_POST, rDCS_AMPH_B1_ODT + (ch * DCS_SPACING), reg_val, false);
// DQS0_ODT
reg_val = *save_region;
save_region++;
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++)
reconfig_command_write(AOP_DDR_AWAKE_POST, rDCS_AMPH_DQS0_ODT + (ch * DCS_SPACING), reg_val, false);
// DQS1_ODT
reg_val = *save_region;
save_region++;
for(ch = 0; ch < DCS_NUM_CHANNELS; ch++)
reconfig_command_write(AOP_DDR_AWAKE_POST, rDCS_AMPH_DQS1_ODT + (ch * DCS_SPACING), reg_val, false);
// rGLBTIMER_ZQCTIMER
reg_val = *save_region;
reconfig_command_write(AOP_DDR_AWAKE_POST, rGLBTIMER_ZQCTIMER, reg_val, false);
save_region++;
}
#endif // #if SUB_PLATFORM_S8001
+849
View File
@@ -0,0 +1,849 @@
/*
* Copyright (C) 2014-2015 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.
*/
/*
* Init Sequence Library for use in:
* Driver for the LPDDR4 compatible DRAM Control Subsystem (DCS) block
*/
/*
Summary of Steps from the Spec (Spreadsheet)
+ (Aa) Steps 0,1,2,3a [need to identify parameterization]
+ (Ab) Step 3b [PMGR: set Freq to 50MHz & delay-wait]
+ (Ac) Steps 3c,4,5 [need to identify parameterization]
+ (B) Step 6 [Change Clk Speed]
+ (C) Step 7 [include delay-wait from early Step 8]
+ (D) Step 8a [Cal: CA 800MHz Vmin]
+ (E) Step 8b [Write Regs]
+ (F) Step 8c [Cal: CA 800MHz Vmin] (...again? should it be CS?)
+ (G) Step 8d [Write Regs]
+ (H) Step 9 [Write Regs]
+ (I) Step 10 [Cal: WrLvl, RdDq, WrDq 800MHz Vmin]
+ (J) Step 11 [Write Regs]
+ (K) Step 12 [Cal: CA 1200MHz Vnom]
+ (L) Step 13 [Write Regs]
+ (M) Step 14 [Cal: WrLvl, RdDq, WrDq 1200MHz Vmin]
+ (N) Steps 15,16,17,18,19,20 [need to identify parameterization]
Between these steps there is possibly a need/desire for:
- Frequency Changes (PMGR)
- PMU save/restore
- debug messages
- register dumps (DV, SiVal)
- anything else!
CONFIG Table:
Compile-Time Known:
Type of Execution Environment CoreOS, DV, SiVal
Type of Target SoC, FPGA, Palladium
ChipID 0x8000, 0x8001, etc.
Revision A0, B0, B1, etc.
Num DCS 4, 8, etc. (Derived...!)
Variant Flags Work-arounds, RADAR Ref., et al.
(Config Info know at Compile time can be subject to #if)
Run-Time Known:
Type of Init ColdBoot, AOP_DDR, AOP_AWAKE
Debug Flags Low-Level, Milestone, et al.
RegValue Table
Much like today's: various values for various registers
Sensitive to ChipID (also Target type?)
(Internal static alloc (Complete Table Fill-in within Init function):
Fill in Values (per ChipID/Rev & Target-type)
return pointer to caller
(Allows customization by caller before use)
TODO:
- Convert to using SPDS for register names, et al
*/
//================================================================================
// API Definitions
#include <drivers/dcs/dcs_init_lib.h>
extern dcs_config_t dcs_cfg;
extern dcs_config_params_t dcs_params;
#if izIBOOT
extern int debug_level_dcs;
#endif
void dcs_enable_autorefresh(void)
{
uint32_t arefen_freq0 = 0x1111013f;
uint32_t arefen_freq1 = 0x11110000;
uint32_t arefen_freq2 = 0x11000000;
uint32_t arefen_freq3 = 0x11100000;
if(dcs_cfg.chipRev < CHIP_REVISION_C0) {
arefen_freq0 = 0x1011013f;
arefen_freq1 = 0x10110000;
arefen_freq2 = 0x10000000;
arefen_freq3 = 0x10100000;
}
// Configure auto-refresh. Freq0 has the auto-refresh enable, so do it last.
dcs_reg_write_all_chan(rDCS_MCU_AREFEN_FREQ(3), arefen_freq3);
dcs_reg_write_all_chan(rDCS_MCU_AREFEN_FREQ(2), arefen_freq2);
dcs_reg_write_all_chan(rDCS_MCU_AREFEN_FREQ(1), arefen_freq1);
dcs_reg_write_all_chan(rDCS_MCU_AREFEN_FREQ(0), arefen_freq0);
}
//================================================================================
// Implementing the Various Steps of the DCS Init, per Specification
// Based on AMC Init Spec (Spreadsheet)
// - Supporting Maui: Spec (v??)
//================================================================================
// Step 0: AMC Prolog
//================================================================================
void dcs_init_Prolog(void)
{
// NOTE: between the Compiler and the Optimization, this should vanish for non-FPGA builds
if (izFPGA && izColdBoot) {
dcs_reg_write_all_chan(rDCS_AMP_DRAM_RESETN(AMP_CA), 1);
delay_for_us(200);
dcs_reg_write_all_chan(rDCS_AMP_DRAM_RESETN(AMP_CA), 0);
delay_for_us(200);
dcs_reg_write_all_chan(rDCS_AMP_DRAM_RESETN(AMP_CA), 1);
delay_for_us(200);
}
}
//================================================================================
// Step 1: AMC Initial Configuration
//================================================================================
void dcs_init_AMC_Initial_Config(void)
{
uint32_t i,n;
// rdar://problem/19137387: this applies to Maui A1 and B0, as well as other SoCs before Cayman
dcs_reg_write(rAMCC_MCCCHNLDEC_ADDR, dcs_params.chnldec);
dcs_reg_write_all_chan(rDCS_SPLLCTRL_CHARGEPUMP, 0x00000068);
dcs_reg_write_all_chan(rDCS_SPLLCTRL_VCO, dcs_params.spllctrl_vco_1);
dcs_reg_write_all_chan(rDCS_SPLLCTRL_VCO, dcs_params.spllctrl_vco_2);
dcs_reg_write_all_chan(rDCS_SPLLCTRL_LDO, 0x00000004);
// This register write to be skipped for Maui A0/A1, but written to for B0 & later, and all other SoCs
if((dcs_cfg.chipID != 0x8000) || (dcs_cfg.chipID == 0x8000 && dcs_cfg.chipRev >= CHIP_REVISION_B0))
dcs_reg_write_all_chan(rDCS_SPLLCTRL_SPLLPWRDNCFG, 0x00000011);
for(i = 0; i < DCS_FREQUENCY_SLOTS; i++) {
for (n = 0; n < dcs_params.num_freqchngctl_regs; n++)
dcs_reg_write_all_chan(rDCS_MCU_FREQCHNGCTL_FREQ(n, i), dcs_params.freq[i].freqchngctl[n]);
// This register write to be skipped for Maui A0/A1, but written to for B0 & later, and all other SoCs
if((dcs_cfg.chipID != 0x8000) || (dcs_cfg.chipID == 0x8000 && dcs_cfg.chipRev >= CHIP_REVISION_B0))
dcs_reg_write_all_chan(rDCS_MCU_FREQCHNGTIM_FREQ(i), dcs_params.freq[i].freqchngtim);
}
if (dcs_cfg.chipRev < CHIP_REVISION_C0)
dcs_reg_write_all_chan(rDCS_MCU_RWCFG, dcs_params.rwcfg);
for(i = AMP_CA ; i < DCS_AMP_NUM_PHYS; i++)
dcs_reg_write_all_chan(rDCS_AMP_DLLUPDTCTRL(i), dcs_params.dllupdtctrl);
dcs_reg_write_all_chan(rDCS_MCU_LAT_FREQ(0), dcs_params.freq[0].lat);
dcs_reg_write_all_chan(rDCS_MCU_LAT_FREQ(1), dcs_params.freq[1].lat);
for(i = 0; i < DCS_FREQUENCY_SLOTS; i++)
dcs_reg_write_all_chan(rDCS_MCU_PHYRDWRTIM_FREQ(i), dcs_params.freq[i].phyrdwrtim);
for(i = 0; i < DCS_FREQUENCY_SLOTS; i++) {
dcs_reg_write_all_chan(rDCS_MCU_CASPCH_FREQ(i), dcs_params.freq[i].caspch);
dcs_reg_write_all_chan(rDCS_MCU_ACT_FREQ(i), dcs_params.freq[i].act);
dcs_reg_write_all_chan(rDCS_MCU_AUTOREF_FREQ(i), dcs_params.freq[i].autoref);
dcs_reg_write_all_chan(rDCS_MCU_SELFREF_FREQ(i), dcs_params.freq[i].selfref);
if (i == 0) dcs_reg_write_all_chan(rDCS_MCU_MODEREG, dcs_params.modereg);
}
dcs_reg_write_all_chan(rDCS_MCU_AUTOREF_PARAMS, dcs_params.autoref_params);
dcs_reg_write_all_chan(rDCS_MCU_PDN, dcs_params.pdn);
dcs_reg_write_all_chan(rDCS_MCU_DERATE_FREQ(0), dcs_params.freq[0].derate);
// These register writes to be skipped for Maui A0/A1, but written to for B0 & later, and all other SoCs
if((dcs_cfg.chipID != 0x8000) || (dcs_cfg.chipID == 0x8000 && dcs_cfg.chipRev >= CHIP_REVISION_B0))
for(i = 1; i < DCS_FREQUENCY_SLOTS; i++)
dcs_reg_write_all_chan(rDCS_MCU_DERATE_FREQ(i), dcs_params.freq[i].derate);
for(i = 0; i < DCS_FREQUENCY_SLOTS; i++)
dcs_reg_write_all_chan(rDCS_MCU_LAT_FREQ(i), dcs_params.freq[i].lat2);
for(i = 0; i < DCS_FREQUENCY_SLOTS; i++)
dcs_reg_write_all_chan(rDCS_MCU_TAT_FREQ(i), dcs_params.freq[i].tat);
dcs_reg_write_all_chan(rDCS_MCU_RNKCFG, dcs_params.rnkcfg);
dcs_reg_write_all_chan(rDCS_MCU_MIFQMAXCTRL_FREQ(0), dcs_params.freq[0].mifqmaxctrl);
dcs_reg_write_all_chan(rDCS_MCU_MIFQMAXCTRL_FREQ(3), dcs_params.freq[3].mifqmaxctrl);
dcs_reg_write_all_chan(rDCS_MCU_PWRMNGTEN, 0);
dcs_reg_write_all_chan(rDCS_MCU_ODTSZQC, 0x00002000);
dcs_reg_write_all_chan(rDCS_MCU_AMCCTRL, 0x00000002);
dcs_reg_write_all_chan(rDCS_MCU_MCPHYUPDTPARAM, 0x15030000);
}
//================================================================================
// Step 2: AMP Initial Configuration
//================================================================================
void dcs_init_AMP_Initial_Config(void)
{
int i;
for(i = AMP_CA ; i < DCS_AMP_NUM_PHYS; i++)
dcs_reg_write_all_chan(rDCS_AMP_AMPEN(i), 0x00000001);
for(i = 0; i < DCS_FREQUENCY_SLOTS; i++)
dcs_reg_write_all_chan(rDCS_AMP_NONDQDSPD_F(i), dcs_params.freq[i].nondqdspd);
for(i = 1; i < DCS_FREQUENCY_SLOTS; i++)
dcs_reg_write_all_chan(rDCS_AMP_NONDQDS_F(i), dcs_params.freq[i].nondqds);
dcs_reg_write_all_chan(rDCS_AMP_CACKCSWKDS, dcs_params.cackcswkds);
for(i = 0; i < DCS_FREQUENCY_SLOTS; i++)
dcs_reg_write_all_chan(rDCS_AMP_VREF_F(AMP_CA, i), dcs_params.freq[i].cavref);
dcs_reg_write_all_chan(rDCS_AMP_ODTENABLE_F(0), dcs_params.freq[0].odt_enable);
dcs_reg_write_all_chan(rDCS_AMP_ODTENABLE_F(1), dcs_params.freq[1].odt_enable);
dcs_reg_write_all_chan(rDCS_AMP_ODTENABLE_F(3), dcs_params.freq[3].odt_enable);
for(i = 0; i < DCS_FREQUENCY_SLOTS; i++) {
// These register writes to be skipped for Maui A0/A1
if((dcs_cfg.chipID != 0x8000) || (dcs_cfg.chipID == 0x8000 && dcs_cfg.chipRev >= CHIP_REVISION_B0)) {
dcs_reg_write_all_chan(rDCS_AMP_DQDS_F(AMP_DQ0,i), dcs_params.freq[i].dqds);
dcs_reg_write_all_chan(rDCS_AMP_DQDS_F(AMP_DQ1,i), dcs_params.freq[i].dqds);
}
dcs_reg_write_all_chan(rDCS_AMP_DQDQSDS_F(AMP_DQ0,i), dcs_params.freq[i].dqdqsds);
dcs_reg_write_all_chan(rDCS_AMP_DQDQSDS_F(AMP_DQ1,i), dcs_params.freq[i].dqdqsds);
}
for(i = 0; i < DCS_FREQUENCY_SLOTS; i++) {
dcs_reg_write_all_chan(rDCS_AMP_VREF_F(AMP_DQ0, i), dcs_params.freq[i].dqvref);
dcs_reg_write_all_chan(rDCS_AMP_VREF_F(AMP_DQ1, i), dcs_params.freq[i].dqvref);
}
dcs_reg_write_all_chan(rDCS_AMP_DQSPDRES(AMP_DQ0), dcs_params.dqspdres);
dcs_reg_write_all_chan(rDCS_AMP_DQSPDRES(AMP_DQ1), dcs_params.dqspdres);
dcs_reg_write_all_chan(rDCS_AMP_SDLL_UPDATE_CNTL(AMP_CA), dcs_params.casdllupdatectrl);
dcs_reg_write_all_chan(rDCS_AMP_SDLL_UPDATE_CNTL(AMP_DQ0), dcs_params.dqsdllupdatectrl);
dcs_reg_write_all_chan(rDCS_AMP_SDLL_UPDATE_CNTL(AMP_DQ1), dcs_params.dqsdllupdatectrl);
dcs_reg_write_all_chan(rDCS_AMP_DIFFMODE_FREQ(AMP_DQ0, 3), 0x1);
dcs_reg_write_all_chan(rDCS_AMP_DIFFMODE_FREQ(AMP_DQ1, 3), 0x1);
dcs_reg_write_all_chan(rDCS_AMP_RDSDLLCTRL(AMP_DQ0), dcs_params.rdsdllctrl_step2);
dcs_reg_write_all_chan(rDCS_AMP_RDSDLLCTRL(AMP_DQ1), dcs_params.rdsdllctrl_step2);
dcs_reg_poll_all_chan(rDCS_AMP_RDSDLLCTRL(AMP_DQ0), dcs_params.rdsdllctrl_step2 & 0x7, 0x0);
dcs_reg_poll_all_chan(rDCS_AMP_RDSDLLCTRL(AMP_DQ1), dcs_params.rdsdllctrl_step2 & 0x7, 0x0);
dcs_reg_write_all_chan(rDCS_AMP_WRDQDQSSDLLCTRL(AMP_DQ0), dcs_params.wrdqdqssdllctrl_step2);
dcs_reg_write_all_chan(rDCS_AMP_WRDQDQSSDLLCTRL(AMP_DQ1), dcs_params.wrdqdqssdllctrl_step2);
dcs_reg_poll_all_chan(rDCS_AMP_WRDQDQSSDLLCTRL(AMP_DQ0), dcs_params.wrdqdqssdllctrl_step2 & 0x7, 0x0);
dcs_reg_poll_all_chan(rDCS_AMP_WRDQDQSSDLLCTRL(AMP_DQ1), dcs_params.wrdqdqssdllctrl_step2 & 0x7, 0x0);
dcs_reg_write_all_chan(rDCS_AMP_CAWRLVLSDLLCODE, dcs_params.cawrlvlsdllcode);
dcs_reg_poll_all_chan(rDCS_AMP_CAWRLVLSDLLCODE, dcs_params.cawrlvlsdllcode & 0x300, 0x000);
if (!izFPGA)
for(i = AMP_CA ; i < DCS_AMP_NUM_PHYS; i++)
dcs_reg_write_all_chan(rDCS_AMP_DLLLOCKTIM(i), dcs_params.dlllocktim);
if(dcs_cfg.chipID == 0x8000 && dcs_cfg.chipRev >= CHIP_REVISION_B0) {
dcs_reg_write_all_chan(rDCS_AMP_DQSPDENALWYSON(AMP_DQ0), 0x00000001);
dcs_reg_write_all_chan(rDCS_AMP_DQSPDENALWYSON(AMP_DQ1), 0x00000001);
}
if((dcs_params.supported_freqs & DCS_FREQ(1)) != 0)
dcs_reg_write_all_chan(rDCS_AMP_DFICALTIMING, dcs_params.dficaltiming);
// These register writes to be skipped for Maui A0/A1
if((dcs_cfg.chipID != 0x8000) || (dcs_cfg.chipID == 0x8000 && dcs_cfg.chipRev >= CHIP_REVISION_B0)) {
for(i = 1; i < DCS_FREQUENCY_SLOTS; i++)
dcs_reg_write_all_chan(rDCS_AMPCA_DFICALTIMING_F(i), dcs_params.freq[i].cadficaltiming);
for(i = 0; i < DCS_FREQUENCY_SLOTS; i++) {
dcs_reg_write_all_chan(rDCS_AMPDQ_DFICALTIMING_F(AMP_DQ0, i), dcs_params.freq[i].dqdficaltiming);
dcs_reg_write_all_chan(rDCS_AMPDQ_DFICALTIMING_F(AMP_DQ1, i), dcs_params.freq[i].dqdficaltiming);
}
dcs_reg_write_all_chan(rDCS_AMP_MDLLCODE_CAP_CNTL(AMP_DQ0), 0x00000002);
dcs_reg_write_all_chan(rDCS_AMP_MDLLCODE_CAP_CNTL(AMP_DQ1), 0x00000002);
}
dcs_reg_write_all_chan(rDCS_AMP_RDWRDQCALTIMING_F(0), dcs_params.rdwrdqcaltiming_f0);
dcs_reg_write_all_chan(rDCS_AMP_RDWRDQCALSEGLEN_F(0), dcs_params.rdwrdqcalseglen_f0);
dcs_reg_write_all_chan(rDCS_AMP_RDWRDQCALTIMING_F(1), dcs_params.rdwrdqcaltiming_f1);
dcs_reg_write_all_chan(rDCS_AMP_RDWRDQCALSEGLEN_F(1), dcs_params.rdwrdqcalseglen_f1);
dcs_reg_write_all_chan(rDCS_AMP_HWRDWRDQCALTIMINGCTRL(1), dcs_params.rdwrdqcaltimingctrl1);
dcs_reg_write_all_chan(rDCS_AMP_HWRDWRDQCALTIMINGCTRL(2), dcs_params.rdwrdqcaltimingctrl2);
dcs_reg_write_all_chan(rDCS_AMP_HWRDDQCALPATPRBS4I, dcs_params.rddqcalpatprbs4i);
dcs_reg_write_all_chan(rDCS_AMP_HWWRDQCALPATPRBS4I, dcs_params.wrdqcalpatprbs4i);
dcs_reg_write_all_chan(rDCS_AMP_RDDQCALWINDOW_F(0), dcs_params.freq[0].rddqcalwindow);
dcs_reg_write_all_chan(rDCS_AMP_WRDQCALWINDOW_F(0), dcs_params.freq[0].wrdqcalwindow);
dcs_reg_write_all_chan(rDCS_AMP_RDDQCALWINDOW_F(1), dcs_params.freq[1].rddqcalwindow);
dcs_reg_write_all_chan(rDCS_AMP_WRDQCALWINDOW_F(1), dcs_params.freq[1].wrdqcalwindow);
dcs_reg_write_all_chan(rDCS_AMP_MAXWRDQS_SDLL_MULFACTOR, dcs_params.maxwrdqssdllmulfactor);
// These register writes to be skipped for Maui A0/A1
if((dcs_cfg.chipID != 0x8000) || (dcs_cfg.chipID == 0x8000 && dcs_cfg.chipRev >= CHIP_REVISION_B0)) {
dcs_reg_write_all_chan(rDCS_AMPDQ_RDDQSMULFACTOR(AMP_DQ0), 0x20181000);
dcs_reg_write_all_chan(rDCS_AMPDQ_RDDQSMULFACTOR(AMP_DQ1), 0x20181000);
}
for(i = 0; i < DCS_FREQUENCY_SLOTS; i++) {
dcs_reg_write_all_chan(rDCS_AMP_CAOUTDLLSCL_FREQ(i), dcs_params.freq[i].caoutdllscl);
dcs_reg_write_all_chan(rDCS_AMP_DQSINDLLSCL_FREQ(AMP_DQ0, i), dcs_params.freq[i].dqsindllscl);
dcs_reg_write_all_chan(rDCS_AMP_DQSINDLLSCL_FREQ(AMP_DQ1, i), dcs_params.freq[i].dqsindllscl);
dcs_reg_write_all_chan(rDCS_AMP_RDCAPCFG_FREQ(AMP_DQ0, i), dcs_params.freq[i].rdcapcfg);
dcs_reg_write_all_chan(rDCS_AMP_RDCAPCFG_FREQ(AMP_DQ1, i), dcs_params.freq[i].rdcapcfg);
}
if (!izFPGA) {
for(i = AMP_CA ; i < DCS_AMP_NUM_PHYS; i++)
dcs_reg_write_all_chan(rDCS_AMP_DLLUPDTCTRL(i), dcs_params.dllupdtctrl1);
dcs_reg_write_all_chan(rDCS_AMP_IMPAUTOCAL, 0x00010000);
}
dcs_reg_write_all_chan(rDCS_AMP_DLLUPDTINTVL(AMP_CA), dcs_params.dllupdtintvl);
dcs_reg_write_all_chan(rDCS_AMP_DLLUPDTINTVL(AMP_DQ0), dcs_params.dllupdtintvl);
dcs_reg_write_all_chan(rDCS_AMP_DLLUPDTINTVL(AMP_DQ1), dcs_params.dllupdtintvl);
for(i = AMP_CA ; i < DCS_AMP_NUM_PHYS; i++)
dcs_reg_write_all_chan(rDCS_AMP_DLLEN(i), 0x00000100);
if(!izFPGA)
{
dcs_reg_write_all_chan(rDCS_AMP_IMPCALCMD, 0x00000000);
}
// Workaround for Maui B0
if((dcs_cfg.chipID == 0x8000 && dcs_cfg.chipRev >= CHIP_REVISION_B0))
dcs_reg_write_all_chan(rDCS_AMP_BISTRXMODE, 0x0000001c);
// AMPH configuration
if(dcs_cfg.chipRev >= CHIP_REVISION_B0)
dcs_reg_write_all_chan(rDCS_AMPH_SLC_REG(0), 0x0000003f);
for(i = AMP_CA ; i < DCS_AMP_NUM_PHYS; i++)
dcs_reg_write_all_chan(rDCS_AMP_AMPINIT(i), 0x00000001);
}
//================================================================================
// Step 3: Self-Refresh Exit
//================================================================================
void dcs_init_Self_Refresh_Exit_a(void)
{
// Wait 5 us after Impedence Calibration to avoid McPhyPending
// preventing the SRFSM from exiting SR.
dcs_spin(5, "after Imp. Cal.");
dcs_reg_write_all_chan(rDCS_MCU_AREFPARAM, dcs_params.arefparam);
for(int i = 0; i < DCS_FREQUENCY_SLOTS; i++)
dcs_reg_write_all_chan(rDCS_MCU_AUTOREF_FREQ(i), dcs_params.freq[i].autoref2);
dcs_reg_write_all_chan(rDCS_MCU_AUTOREF_PARAMS, dcs_params.autoref_params2);
if(izFPGA)
if(dcs_cfg.chipRev < CHIP_REVISION_B0)
dcs_reg_write_all_chan(rDCS_MCU_AUTOREF_PARAMS, dcs_params.autoref_params);
dcs_reg_write_all_chan(rDCS_MCU_ODTSZQC, dcs_params.odtszqc);
dcs_reg_write_all_chan(rDCS_MCU_LONGSR, dcs_params.longsr);
dcs_reg_write_all_chan(rDCS_MCU_MCPHYUPDTPARAM, 0x15030007);
}
//========================================
// Caller Code should:
// - Change Frequency to 50MHz
//========================================
void dcs_init_Self_Refresh_Exit_b(void)
{
dcs_reg_write_all_chan(rDCS_MCU_AMCCTRL, 0x00000003);
if (!izFPGA) {
dcs_reg_write_all_chan(rDCS_AMP_IMPCALCMD, 0x00000001);
dcs_reg_poll_all_chan(rDCS_AMP_IMPCALCMD, 0x01, 0x00);
}
if (izResume)
dcs_enable_autorefresh();
dcs_spin(2200, "After Enable Auto-Refresh");
if((dcs_cfg.chipID != 0x8000) || (dcs_cfg.chipID == 0x8000 && dcs_cfg.chipRev >= CHIP_REVISION_B0)) {
dcs_reg_write_all_chan(rDCS_MCU_FREQCHNGCTL, dcs_params.freqchngctl_step3);
dcs_reg_poll_all_chan(rDCS_MCU_FREQCHNGCTL, 0x10000, 0x00000);
dcs_spin(2, "After SoC Update");
}
// Resume-Boot and Cold-Boot use different Exit commands for Self-Refresh
// Issue self-refresh exit cmd for resume boot with MPC
int n = (izColdBoot)? 0x00000000:0x00004000;
// Issue self-refresh exit cmd for resume boot with MPC
dcs_reg_write_all_chan(rDCS_MCU_MRINITCMD_0, n);
dcs_reg_write_all_chan(rDCS_MCU_MRINITCMD_0, n | 0x1);
dcs_reg_poll_all_chan(rDCS_MCU_MRINITCMD_0, 0x01, 0x00);
dcs_spin(2, NULL);
dcs_reg_write(rGLBTIMER_CHEN, (1 << dcs_cfg.num_dcs) - 1);
}
//================================================================================
// Step 4: DRAM Reset, ZQ Calibration & Configuration (cold boot only)
//================================================================================
void dcs_init_ZQ_Cal_Cfg(void)
{
// ZQ calibration START MPC cmd
dcs_mrcmd(MR_MPC, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x0, 0x4f);
// wait 1us for tZQCAL
dcs_spin(1, "tZQCAL");
// ZQ calibration LATCH MPC cmd
dcs_mrcmd(MR_MPC, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x0, 0x51);
// wait 10ns for tZQLAT
dcs_spin(1, "tZQLAT");
if (izColdBoot) {
// MR2 register (read/write latency)
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x2, 0x0);
// MR1 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x1, 0x8e);
// MR3 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x3, dcs_params.mr3cmd);
// MR22 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x16, 0x0);
// MR11 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0xb, 0x0);
// MR13 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0xd, dcs_params.mr13cmd);
// MR12 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0xc, 0x59);
// MR14 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0xe, 0x59);
// MR23 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x17, 0x80);
uint32_t patinvertmask = (DCS_REG_READ_CH(0, rDCS_AMP_HWRDDQCALPATPRBS4I) >> 16) & 0xffff;
uint32_t prbs = DCS_REG_READ_CH(0, rDCS_AMP_HWWRDQCALPATPRBS4I);
// MR15 register
dcs_mrcmd(MR_MPC, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0xf, patinvertmask & 0xff);
// MR20 register
dcs_mrcmd(MR_MPC, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x14, (patinvertmask >> 8) & 0xff);
// MR32 register
dcs_mrcmd(MR_MPC, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x20, prbs & 0xff);
// MR40 register
dcs_mrcmd(MR_MPC, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x28, (prbs >> 8) & 0xff);
}
}
//================================================================================
// Step 5a: AddrConfig Configuration
//================================================================================
void dcs_init_AddrCfg_Cfg(void)
{
dcs_reg_write(rAMCC_ADDRCFG_ADDR, dcs_params.addrcfg);
}
//========================================
// Caller Code should:
// - Use MR Cmds to Query the Device
//========================================
//================================================================================
// Step 5b: Total Mem Size Config
//================================================================================
void dcs_init_TotalSize_Cfg(uint32_t total_size_Mbytes)
{
dbgprintf(DCS_DBG_ASSESS_CONFIG, "Memory_size: %llu bytes\n",
(((uint64_t)total_size_Mbytes) * MEG * NUM_AMCCS));
// (Units of 128 MBs in the register)
dcs_reg_write(rAMCC_DRAMACCCTRL_ADDR, ((total_size_Mbytes / NUM_AMCCS) / DCS_NUM_MEG_IN_DRAM_BLK) - 1);
dcs_reg_write(rAMCC_MCCCHNLDEC_ADDR, dcs_params.chnldec);
dbgprintf(DCS_DBG_ASSESS_CONFIG, "rAMCC_DRAMACCCTRL: 0x%08x\n", rAMCC_DRAMACCCTRL);
}
//================================================================================
// Step 6: Switch from boot-clock speed to normal operation speed
//================================================================================
void dcs_init_Reenable_AMC_Scheduler(void)
{
// Wait 5 us before freq change to make sure all refreshes have been flushed
dcs_spin(5, "After Refresh");
// Enable (again) the AMC Scheduler
dcs_reg_write_all_chan(rDCS_MCU_AMCCTRL, 0x00000003);
}
//================================================================================
// Step 7: Setup registers for CA calibration for bucket 1
//================================================================================
void dcs_init_CA_Cal_Setup_Freq1(void)
{
// MR13 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0xd, dcs_params.mr13cmd_step7);
if (izColdBoot) {
if (izFPGA) {
// MR11 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0xb, 0x00);
} else {
// MR2 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x2, 0x52);
// MR1 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x1, 0xae);
// MR3 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x3, dcs_params.mr3cmd_step7);
// MR22 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x16, dcs_params.mr22cmd);
// MR11 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0xb, dcs_params.mr11cmd);
// MR12 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0xc, 0x11);
// MR14 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0xe, 0x11);
}
dcs_reg_write_all_chan(rDCS_AMP_CAWRLVLSDLLCODE, 0x00000200);
dcs_reg_poll_all_chan(rDCS_AMP_CAWRLVLSDLLCODE, 0x0200, 0x0000);
}
}
//================================================================================
// Step 8: AMP Dynamic CA Vref Timing Calibration at Vmin 800MHz
//================================================================================
void dcs_init_CA_Cal_Freq1(void)
{
// Nothing to be done at this step for cold boot
}
//================================================================================
// Step 9: Setup registers for DQ calibration for bucket 1
//================================================================================
void dcs_init_DQ_Cal_Setup_Freq1_a(void)
{
int i;
if (izColdBoot) {
// MR13 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0xd, dcs_params.mr13cmd_step9);
}
dcs_spin(1, NULL);
if(izResume) {
dcs_reg_write_all_chan(rDCS_MCU_PWRMNGTEN, 0x00000002);
dcs_reg_write_all_chan(rDCS_MCU_FREQCHNGCTL, 0x01008888);
for(i = AMP_DQ0 ; i < DCS_AMP_NUM_PHYS; i++)
dcs_reg_write_all_chan(rDCS_AMP_WRDQDQSSDLLCTRL(i), 0xFF00000C);
for(i = AMP_CA ; i < DCS_AMP_NUM_PHYS; i++)
dcs_reg_write_all_chan(rDCS_AMP_SDLL_UPDATE_DEFER_EN(i), 0x00000000);
for(i = AMP_DQ0; i < DCS_AMP_NUM_PHYS; i++)
dcs_reg_write_all_chan(rDCS_AMP_MDLLOVRRD(i), 0x00000000);
}
}
// Caller code should change frequency to bucket 1
void dcs_init_DQ_Cal_Setup_Freq1_b(void)
{
if (izColdBoot) {
if((dcs_cfg.chipID != 0x8000) || (dcs_cfg.chipID == 0x8000 && dcs_cfg.chipRev >= CHIP_REVISION_B0)) {
dcs_reg_write_all_chan(rDCS_MCU_FREQCHNGCTL, dcs_params.freqchngctl_step9);
dcs_reg_poll_all_chan(rDCS_MCU_FREQCHNGCTL, 0x10000, 0x00000);
// Wait 2us for the soc update to finish
dcs_spin(2, NULL);
}
}
}
//================================================================================
// Step 10: PHY write DQ calibration
//================================================================================
void dcs_init_wrdq_skew(void)
{
dcs_reg_write_all_chan(rDCS_AMP_DQSDQ_SKEWCTL(AMP_DQ0), 0x06000000);
dcs_reg_write_all_chan(rDCS_AMP_DQSDQ_SKEWCTL(AMP_DQ1), 0x06000000);
}
void dcs_init_post_wrlvl(void)
{
if(dcs_cfg.chipID == 0x8000 && dcs_cfg.chipRev >= CHIP_REVISION_B0) {
dcs_reg_write_all_chan(rDCS_AMP_DQFLTCTRL(AMP_DQ0), 0x00000010);
dcs_reg_write_all_chan(rDCS_AMP_DQFLTCTRL(AMP_DQ1), 0x00000010);
}
}
//================================================================================
// Step 11: Setup registers for CA calibration for bucket 0
//================================================================================
void dcs_init_CA_Cal_Setup_Freq0(void)
{
if (izColdBoot) {
if(dcs_cfg.chipID == 0x8000 && dcs_cfg.chipRev >= CHIP_REVISION_B0) {
dcs_reg_write_all_chan(rDCS_AMP_DQFLTCTRL(AMP_DQ0), 0x00000000);
dcs_reg_write_all_chan(rDCS_AMP_DQFLTCTRL(AMP_DQ1), 0x00000000);
}
// MR13 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x0d, dcs_params.mr13cmd_step11);
if (!izFPGA) {
// MR2 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x02, dcs_params.mr2cmd_step11);
// MR1 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x01, dcs_params.mr1cmd_step11);
// MR3 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x03, dcs_params.mr3cmd_step11);
}
// MR22 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x16, dcs_params.mr22cmd_step11);
// MR11 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x0b, (izFPGA) ? 0x00 : dcs_params.mr11cmd_step11);
// MR12 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x0c, dcs_params.mr12cmd_step11);
// MR14 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x0e, dcs_params.mr14cmd_step11);
if((dcs_params.supported_freqs & DCS_FREQ(1)) == 0) {
dcs_reg_write_all_chan(rDCS_AMP_CAWRLVLSDLLCODE, 0x00000200);
dcs_reg_poll_all_chan(rDCS_AMP_CAWRLVLSDLLCODE, 0x200, 0x000);
}
}
}
//================================================================================
// Step 12: AMP Dynamic CA Timing Calibration
//================================================================================
//================================================================================
// Step 13: Setup registers for DQ calibration for bucket 0
//================================================================================
void dcs_init_DQ_Cal_Setup_Freq0_a(void)
{
if (izColdBoot) {
// MR13 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x0d, dcs_params.mr13cmd_step13);
// Wait 1 us
dcs_spin(1, NULL);
}
}
void dcs_init_DQ_Cal_Setup_Freq0_b(void)
{
if (izColdBoot) {
if((dcs_cfg.chipID != 0x8000) || (dcs_cfg.chipID == 0x8000 && dcs_cfg.chipRev >= CHIP_REVISION_B0)) {
dcs_reg_write_all_chan(rDCS_MCU_FREQCHNGCTL, 0x00010000);
dcs_reg_poll_all_chan(rDCS_MCU_FREQCHNGCTL, 0x10000, 0x00000);
// Wait 2us for the soc update to finish
dcs_spin(2, NULL);
}
}
}
//================================================================================
// Step 14: AMP Dynamic DQ Calibration
//================================================================================
//================================================================================
// Step 15: Setup Registers for Boot
//================================================================================
void dcs_init_Reg_for_Boot(void)
{
if((dcs_cfg.chipID == 0x8000 && dcs_cfg.chipRev >= CHIP_REVISION_B0))
dcs_reg_write_all_chan(rDCS_AMP_BISTRXMODE, 0x00000000);
if(dcs_cfg.chipRev >= CHIP_REVISION_C0)
dcs_reg_write_all_chan(rDCS_AMPH_SLC_REG(0), 0x0000013f);
#ifndef DCS_RUN_AT_50MHZ
if (izColdBoot) {
// MR13 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x0d, dcs_params.mr13cmd_step15);
}
#endif
if(izFPGA && !(dcs_params.supported_freqs & DCS_FREQ(1)))
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x0d, 0x50);
// Wait 1 us
dcs_spin(1, NULL);
if (izColdBoot) {
dcs_reg_write_all_chan(rDCS_MCU_FREQCHNGCTL, dcs_params.freqchngctl_step15);
dcs_reg_write_all_chan(rDCS_AMP_WRDQDQSSDLLCTRL(AMP_DQ0), 0xff000008);
dcs_reg_write_all_chan(rDCS_AMP_WRDQDQSSDLLCTRL(AMP_DQ1), 0xff000008);
#if !DCS_DO_CALIBRATION
// skip these for all silicon targets, where calibration is performed, also skip for any Maui A1 target
if((dcs_cfg.chipID != 0x8000) || (dcs_cfg.chipID == 0x8000 && dcs_cfg.chipRev >= CHIP_REVISION_B0)) {
dcs_reg_write_all_chan(rDCS_AMP_RDSDLLCTRL(AMP_DQ0), dcs_params.rdsdllctrl_step15);
dcs_reg_write_all_chan(rDCS_AMP_RDSDLLCTRL(AMP_DQ1), dcs_params.rdsdllctrl_step15);
dcs_reg_poll_all_chan(rDCS_AMP_RDSDLLCTRL(AMP_DQ0), dcs_params.rdsdllctrl_step15 & 0x7, 0x0);
dcs_reg_poll_all_chan(rDCS_AMP_RDSDLLCTRL(AMP_DQ1), dcs_params.rdsdllctrl_step15 & 0x7, 0x0);
}
#endif
}
dcs_reg_write_all_chan(rDCS_AMP_HWRDWRDQCALFULLSCANEN, 0x00000000);
dcs_reg_write_all_chan(rDCS_AMP_HWRDWRDQCALFULLSCANEN, 0x00000003);
}
//================================================================================
// Step 16: Enable Other Features
//================================================================================
void dcs_init_MoreFeatures(void)
{
dcs_reg_write_all_chan(rDCS_MCU_AREFPARAM, dcs_params.arefparam);
dcs_reg_write_all_chan(rDCS_MCU_ODTSZQC, dcs_params.odtszqc2);
dcs_reg_write_all_chan(rDCS_MCU_QBREN, dcs_params.qbren_step16);
if (izColdBoot)
dcs_enable_autorefresh();
}
//================================================================================
// Step 17: Enable Fast Critical Word Forwarding Feature
//================================================================================
void dcs_init_Fast_Critical_Word_Forwarding(void)
{
dcs_reg_write_all_chan(rDCS_MCU_QBRPARAM, dcs_params.qbrparam);
dcs_reg_write_all_chan(rDCS_MCU_QBREN, dcs_params.qbren);
dcs_reg_poll(rAMCC_MCCPWRONWAYCNTSTATUS_ADDR, 0x7fff7fff, 0x42104210);
dcs_reg_write(rAMCC_MCC0QPROPCTRL_ADDR, 0x300011a2);
dcs_reg_write(rAMCC_MCC1QPROPCTRL_ADDR, 0x300011a2);
dcs_reg_write(rAMCC_MCCGEN_ADDR, dcs_params.mccgen);
}
//================================================================================
// Step 18: Enable Power- and Clock-Gating Features; Config MCC and Global Timers
//================================================================================
void dcs_init_Gating_Global_Timers(void)
{
const struct dcs_memory_device_info *dev_info = dcs_get_memory_device_info();
dcs_reg_write_all_chan(rDCS_AMP_AMPCLK(AMP_CA), dcs_params.caampclk);
dcs_reg_write_all_chan(rDCS_AMP_AMPCLK(AMP_DQ0), dcs_params.dqampclk);
dcs_reg_write_all_chan(rDCS_AMP_AMPCLK(AMP_DQ1), dcs_params.dqampclk);
dcs_reg_write_all_chan(rDCS_MCU_PWRMNGTEN, dcs_params.pwrmngten);
if(!izFPGA) {
dcs_reg_write_all_chan(rDCS_MCU_PWRMNGTPARAM_FREQ(0), 0x01800000);
dcs_reg_write_all_chan(rDCS_MCU_PSQWQCTL1, 0x01640120);
}
// Global Timer Setup
if(dcs_cfg.chipID == 0x8000 && dcs_cfg.chipRev < CHIP_REVISION_B0) {
dcs_reg_write(rGLBTIMER_PMGRWAKEUPCFG, 0x0000ff);
dcs_reg_write(rGLBTIMER_MDLLTIMER, 0x000bb8); // 3000
dcs_reg_write(rGLBTIMER_MDLLVOLTRAMPTIMER, 0x00004b); // 75
dcs_reg_write(rGLBTIMER_CTRLUPDMASKTIMER, 0x00000f); // 15
dcs_reg_write(rGLBTIMER_RDCALTIMER, 0x2dc6c0); // 3000000
dcs_reg_write(rGLBTIMER_WRCALTIMER, 0x2dc6c0); // 3000000
dcs_reg_write(rGLBTIMER_ZQCTIMER, 0x3d0900); // 4000000
dcs_reg_write(rGLBTIMER_PERCAL_FREQCHNGTIMER, 0x000001); // 300000
dcs_reg_write(rGLBTIMER_VOLTRAMPTIMER, 0x000001); // 300000
dcs_reg_write(rGLBTIMER_IMPCALTIMER, 0x002ee0); // 12000
} else {
dcs_reg_write(rGLBTIMER_PMGRWAKEUPCFG, 0x0000ff);
dcs_reg_write(rGLBTIMER_PREFREQ2ALLBANKDLY(0), 0x01500150);
dcs_reg_write(rGLBTIMER_PREFREQ2ALLBANKDLY(1), 0x01500150);
dcs_reg_write(rGLBTIMER_PREFREQCHNG2FREQCHNGDLY(0), 0x02a002a0);
dcs_reg_write(rGLBTIMER_PREFREQCHNG2FREQCHNGDLY(1), 0x02a002a0);
dcs_reg_write(rGLBTIMER_CAL2PREFREQCHNGDLY(0), 0x00900090);
dcs_reg_write(rGLBTIMER_CAL2PREFREQCHNGDLY(1), 0x00900090);
dcs_reg_write(rGLBTIMER_FREQCHNG2PSTCALDLY(0), 0x01200120);
dcs_reg_write(rGLBTIMER_FREQCHNG2PSTCALDLY(1), 0x01200120);
dcs_reg_write(rGLBTIMER_MDLLTIMER, 0x000bb8); // 3000
dcs_reg_write(rGLBTIMER_MDLLVOLTRAMPTIMER, 0x00004b); // 75
dcs_reg_write(rGLBTIMER_CTRLUPDMASKTIMER, 0x00000f); // 15
// skip IDTTIMER setup per spec
//dcs_reg_write(rGLBTIMER_IDTTIMER, 0x007530); // 30000
dcs_reg_write(rGLBTIMER_RDCALTIMER, 0x2dc6c0); // 3000000
dcs_reg_write(rGLBTIMER_WRCALTIMER, 0x2dc6c0); // 3000000
// <rdar://problem/23355941> Maui/Malta: Samsung DRAM workaround: disable hw zqcal
if(! ((dev_info->vendor_id == JEDEC_LPDDR4_MANUF_ID_SAMSUNG) && (dev_info->rev_id == 5) && (dev_info->rev_id2 <= 1)) )
dcs_reg_write(rGLBTIMER_ZQCTIMER, 0x3d0900); // 4000000
dcs_reg_write(rGLBTIMER_PERCAL_FREQCHNGTIMER, 0x0493e0); //
dcs_reg_write(rGLBTIMER_VOLTRAMPTIMER, 0x0493e0); //
dcs_reg_write(rGLBTIMER_IMPCALTIMER, 0x002ee0); // 12000
dcs_reg_write(rGLBTIMER_VOLTRAMP2ALLBANKDLY(0), 0x00d800d8);
dcs_reg_write(rGLBTIMER_VOLTRAMP2ALLBANKDLY(1), 0x00d800d8);
dcs_reg_write(rGLBTIMER_ALLBANK2PMGRACKDLY(0), 0x00900090);
dcs_reg_write(rGLBTIMER_ALLBANK2PMGRACKDLY(1), 0x00900090);
}
// Dynamic Clk & Power Gating
dcs_reg_write_all_chan(rDCS_MCU_AMCCLKPWRGATE, 0x050a0000);
}
//================================================================================
// Step 19: ODTS read & set interval for periodic MR4 on-die Temp sensor reading
//================================================================================
void dcs_init_ODTS(void)
{
uint8_t temp[16*8]; // Far more Channels/Ranks than we are likely ever to have/need
// INSTEAD OF: uint8_t temp[dcs_cfg.num_dcs * dcs_cfg.num_rank];
// MR4 read to bring memory out of self-refresh
dcs_mrcmd(MR_READ, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x4, (uintptr_t)temp);
dcs_reg_write_all_chan(rDCS_MCU_ODTSZQC, dcs_params.odtszqc3);
}
//================================================================================
+963
View File
@@ -0,0 +1,963 @@
/*
* Copyright (C) 2014-2015 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.
*/
/*
* Init Sequence Library for use in:
* Driver for the LPDDR4 compatible DRAM Control Subsystem (DCS) block
*/
/*
Summary of Steps from the Spec (Spreadsheet)
+ (Aa) Steps 0,1,2,3a [need to identify parameterization]
+ (Ab) Step 3b [PMGR: set Freq to 50MHz & delay-wait]
+ (Ac) Steps 3c,4,5 [need to identify parameterization]
+ (B) Step 6 [Change Clk Speed]
+ (C) Step 7 [include delay-wait from early Step 8]
+ (D) Step 8a [Cal: CA 800MHz Vmin]
+ (E) Step 8b [Write Regs]
+ (F) Step 8c [Cal: CA 800MHz Vmin] (...again? should it be CS?)
+ (G) Step 8d [Write Regs]
+ (H) Step 9 [Write Regs]
+ (I) Step 10 [Cal: WrLvl, RdDq, WrDq 800MHz Vmin]
+ (J) Step 11 [Write Regs]
+ (K) Step 12 [Cal: CA 1200MHz Vnom]
+ (L) Step 13 [Write Regs]
+ (M) Step 14 [Cal: WrLvl, RdDq, WrDq 1200MHz Vmin]
+ (N) Steps 15,16,17,18,19,20 [need to identify parameterization]
Between these steps there is possibly a need/desire for:
- Frequency Changes (PMGR)
- PMU save/restore
- debug messages
- register dumps (DV, SiVal)
- anything else!
CONFIG Table:
Compile-Time Known:
Type of Execution Environment CoreOS, DV, SiVal
Type of Target SoC, FPGA, Palladium
ChipID 0x8000, 0x8001, etc.
Revision A0, B0, B1, etc.
Num DCS 4, 8, etc. (Derived...!)
Variant Flags Work-arounds, RADAR Ref., et al.
(Config Info know at Compile time can be subject to #if)
Run-Time Known:
Type of Init ColdBoot, AOP_DDR, AOP_AWAKE
Debug Flags Low-Level, Milestone, et al.
RegValue Table
Much like today's: various values for various registers
Sensitive to ChipID (also Target type?)
(Internal static alloc (Complete Table Fill-in within Init function):
Fill in Values (per ChipID/Rev & Target-type)
return pointer to caller
(Allows customization by caller before use)
TODO:
- Convert to using SPDS for register names, et al
*/
//================================================================================
// API Definitions
#include <drivers/dcs/dcs_init_lib.h>
extern dcs_config_t dcs_cfg;
extern dcs_config_params_t dcs_params;
#if izIBOOT
extern int debug_level_dcs;
#endif
// <rdar://problem/23244578>: To track throughout the sequence whether we should apply the Samsung DRAM workarounds
static bool apply_samsung_workaround = false;
void dcs_enable_autorefresh(void)
{
uint32_t arefen_freq0 = 0x1011013f;
uint32_t arefen_freq1 = 0x10010000;
// Configure auto-refresh. Freq0 has the auto-refresh enable, so do it last.
dcs_reg_write_all_chan(rDCS_MCU_AREFEN_FREQ(3), 0x10100000);
dcs_reg_write_all_chan(rDCS_MCU_AREFEN_FREQ(2), 0x10000000);
dcs_reg_write_all_chan(rDCS_MCU_AREFEN_FREQ(1), arefen_freq1);
dcs_reg_write_all_chan(rDCS_MCU_AREFEN_FREQ(0), arefen_freq0);
}
//================================================================================
// Implementing the Various Steps of the DCS Init, per Specification
// Based on AMC Init Spec (Spreadsheet)
// - Supporting Maui: Spec (v??)
//================================================================================
// Step 0: AMC Prolog
//================================================================================
void dcs_init_Prolog(void)
{
// NOTE: between the Compiler and the Optimization, this should vanish for non-FPGA builds
if (izFPGA && izColdBoot) {
dcs_reg_write_all_chan(rDCS_AMP_DRAM_RESETN(AMP_CA), 1);
delay_for_us(200);
dcs_reg_write_all_chan(rDCS_AMP_DRAM_RESETN(AMP_CA), 0);
delay_for_us(200);
dcs_reg_write_all_chan(rDCS_AMP_DRAM_RESETN(AMP_CA), 1);
delay_for_us(200);
}
}
//================================================================================
// Step 1: AMC Initial Configuration
//================================================================================
void dcs_init_AMC_Initial_Config(void)
{
uint32_t i,n;
// rdar://problem/19137387: this applies to Maui A1 and B0, as well as other SoCs before Cayman
dcs_reg_write(rAMCC_MCCCHNLDEC_ADDR, dcs_params.chnldec);
#if NUM_AMCCS == 2
dcs_reg_write(rAMCC1_MCCCHNLDEC_ADDR, dcs_params.chnldec);
#endif
dcs_reg_write_all_chan(rDCS_SPLLCTRL_CHARGEPUMP, 0x00000068);
dcs_reg_write_all_chan(rDCS_SPLLCTRL_MODEREG, 0x1);
dcs_reg_write_all_chan(rDCS_SPLLCTRL_VCO, dcs_params.spllctrl_vco_1);
dcs_reg_write_all_chan(rDCS_SPLLCTRL_VCO, dcs_params.spllctrl_vco_2);
dcs_reg_write_all_chan(rDCS_SPLLCTRL_LDO, 0x00000004);
// This register write to be skipped for Maui A0/A1, but written to for B0 & later, and all other SoCs
if((dcs_cfg.chipID != 0x8000) || (dcs_cfg.chipID == 0x8000 && dcs_cfg.chipRev >= CHIP_REVISION_B0))
dcs_reg_write_all_chan(rDCS_SPLLCTRL_SPLLPWRDNCFG, 0x00000011);
for(i = 0; i < DCS_FREQUENCY_SLOTS; i++) {
for (n = 0; n < dcs_params.num_freqchngctl_regs; n++)
dcs_reg_write_all_chan(rDCS_MCU_FREQCHNGCTL_FREQ(n, i), dcs_params.freq[i].freqchngctl[n]);
// This register write to be skipped for Maui A0/A1, but written to for B0 & later, and all other SoCs
if((dcs_cfg.chipID != 0x8000) || (dcs_cfg.chipID == 0x8000 && dcs_cfg.chipRev >= CHIP_REVISION_B0))
dcs_reg_write_all_chan(rDCS_MCU_FREQCHNGTIM_FREQ(i), dcs_params.freq[i].freqchngtim);
}
dcs_reg_write_all_chan(rDCS_AMP_WRDQCALVREFCODECONTROL, dcs_params.wrdqcalvrefcodecontrol);
dcs_reg_write_all_chan(rDCS_AMP_RDDQCALVREFCODECONTROL, dcs_params.rddqcalvrefcodecontrol);
dcs_reg_write_all_chan(rDCS_AMP_HWRDDQCALVREFCONTROL, 0x01d0b060);
dcs_reg_write_all_chan(rDCS_AMP_HWRDDQCALVREFOFFSETCONTROL(1), 0x06040200);
dcs_reg_write_all_chan(rDCS_AMP_HWRDDQCALVREFOFFSETCONTROL(2), 0x00fafcfe);
dcs_reg_write_all_chan(rDCS_AMP_HWWRDQCALVREFCONTROL, 0x02200060);
dcs_reg_write_all_chan(rDCS_AMP_HWWRDQCALVREFOFFSETCONTROL(1), 0x06040200);
dcs_reg_write_all_chan(rDCS_AMP_HWWRDQCALVREFOFFSETCONTROL(2), 0x00fafcfe);
dcs_reg_write(rGLBTIMER_PERVREFCALCFG, 0x00000003);
dcs_reg_write(rGLBTIMER_VREFCNTRL, 0x00060006);
dcs_reg_write_all_chan(rDCS_MCU_MODEREG, 0x120c90b8);
if (dcs_cfg.chipRev < CHIP_REVISION_B0)
{
dcs_reg_write_all_chan(rDCS_MCU_RWCFG, dcs_params.rwcfg);
}
for(i = AMP_CA ; i < DCS_AMP_NUM_PHYS; i++)
dcs_reg_write_all_chan(rDCS_AMP_DLLUPDTCTRL(i), dcs_params.dllupdtctrl);
dcs_reg_write_all_chan(rDCS_MCU_LAT_FREQ(0), dcs_params.freq[0].lat);
dcs_reg_write_all_chan(rDCS_MCU_LAT_FREQ(1), dcs_params.freq[1].lat);
for(i = 0; i < DCS_FREQUENCY_SLOTS; i++)
dcs_reg_write_all_chan(rDCS_MCU_PHYRDWRTIM_FREQ(i), dcs_params.freq[i].phyrdwrtim);
for(i = 0; i < DCS_FREQUENCY_SLOTS; i++) {
dcs_reg_write_all_chan(rDCS_MCU_CASPCH_FREQ(i), dcs_params.freq[i].caspch);
dcs_reg_write_all_chan(rDCS_MCU_ACT_FREQ(i), dcs_params.freq[i].act);
dcs_reg_write_all_chan(rDCS_MCU_AUTOREF_FREQ(i), dcs_params.freq[i].autoref);
dcs_reg_write_all_chan(rDCS_MCU_SELFREF_FREQ(i), dcs_params.freq[i].selfref);
if (i == 0) dcs_reg_write_all_chan(rDCS_MCU_MODEREG, dcs_params.modereg);
}
dcs_reg_write_all_chan(rDCS_MCU_AUTOREF_PARAMS, dcs_params.autoref_params);
dcs_reg_write_all_chan(rDCS_MCU_PDN, dcs_params.pdn);
dcs_reg_write_all_chan(rDCS_MCU_DERATE_FREQ(0), dcs_params.freq[0].derate);
// These register writes to be skipped for Maui A0/A1, but written to for B0 & later, and all other SoCs
if((dcs_cfg.chipID != 0x8000) || (dcs_cfg.chipID == 0x8000 && dcs_cfg.chipRev >= CHIP_REVISION_B0))
for(i = 1; i < DCS_FREQUENCY_SLOTS; i++)
dcs_reg_write_all_chan(rDCS_MCU_DERATE_FREQ(i), dcs_params.freq[i].derate);
for(i = 0; i < DCS_FREQUENCY_SLOTS; i++)
dcs_reg_write_all_chan(rDCS_MCU_LAT_FREQ(i), dcs_params.freq[i].lat2);
for(i = 0; i < DCS_FREQUENCY_SLOTS; i++)
dcs_reg_write_all_chan(rDCS_MCU_TAT_FREQ(i), dcs_params.freq[i].tat);
dcs_reg_write_all_chan(rDCS_MCU_RNKCFG, dcs_params.rnkcfg);
dcs_reg_write_all_chan(rDCS_MCU_MIFQMAXCTRL_FREQ(0), dcs_params.freq[0].mifqmaxctrl);
dcs_reg_write_all_chan(rDCS_MCU_MIFQMAXCTRL_FREQ(3), dcs_params.freq[3].mifqmaxctrl);
dcs_reg_write_all_chan(rDCS_MCU_PWRMNGTEN, 0);
dcs_reg_write_all_chan(rDCS_MCU_ODTSZQC, 0x00002000);
dcs_reg_write_all_chan(rDCS_MCU_AMCCTRL, 0x00000002);
dcs_reg_write_all_chan(rDCS_MCU_MCPHYUPDTPARAM, 0x15030000);
}
//================================================================================
// Step 2: AMP Initial Configuration
//================================================================================
void dcs_init_AMP_Initial_Config(void)
{
int i;
if (dcs_cfg.chipRev < CHIP_REVISION_B0)
{
dcs_reg_write_all_chan(rDCS_AMPH_DCC_BYPCK, 0x00003f3f);
dcs_reg_write_all_chan(rDCS_AMPH_DCC_BYPCS, 0x00003f3f);
dcs_reg_write_all_chan(rDCS_AMPH_DCC_BYPB0, 0x00003f3f);
dcs_reg_write_all_chan(rDCS_AMPH_DCC_BYPDQS0, 0x00003f3f);
dcs_reg_write_all_chan(rDCS_AMPH_DCC_BYPB1, 0x00003f3f);
dcs_reg_write_all_chan(rDCS_AMPH_DCC_BYPDQS1, 0x00003f3f);
dcs_reg_write_all_chan(rDCS_AMPH_DCC_BYPCA, 0x00003f3f);
dcs_reg_write_all_chan(rDCS_AMPH_DCC_BYPCK, 0x00013f3f);
dcs_reg_write_all_chan(rDCS_AMPH_DCC_BYPCS, 0x00013f3f);
dcs_reg_write_all_chan(rDCS_AMPH_DCC_BYPB0, 0x00013f3f);
dcs_reg_write_all_chan(rDCS_AMPH_DCC_BYPDQS0, 0x00013f3f);
dcs_reg_write_all_chan(rDCS_AMPH_DCC_BYPB1, 0x00013f3f);
dcs_reg_write_all_chan(rDCS_AMPH_DCC_BYPDQS1, 0x00013f3f);
dcs_reg_write_all_chan(rDCS_AMPH_DCC_BYPCA, 0x00013f3f);
}
for(i = AMP_CA ; i < DCS_AMP_NUM_PHYS; i++)
dcs_reg_write_all_chan(rDCS_AMP_AMPEN(i), 0x00000001);
for(i = 0; i < DCS_FREQUENCY_SLOTS; i++)
dcs_reg_write_all_chan(rDCS_AMP_VREF_F(AMP_CA, i), dcs_params.freq[i].cavref);
dcs_reg_write_all_chan(rDCS_AMP_ODTENABLE_F(0), dcs_params.freq[0].odt_enable);
dcs_reg_write_all_chan(rDCS_AMP_ODTENABLE_F(1), dcs_params.freq[1].odt_enable);
dcs_reg_write_all_chan(rDCS_AMP_ODTENABLE_F(3), dcs_params.freq[3].odt_enable);
for(i = 0; i < DCS_FREQUENCY_SLOTS; i++) {
dcs_reg_write_all_chan(rDCS_AMP_VREF_F(AMP_DQ0, i), dcs_params.freq[i].dqvref);
dcs_reg_write_all_chan(rDCS_AMP_VREF_F(AMP_DQ1, i), dcs_params.freq[i].dqvref);
}
dcs_reg_write_all_chan(rDCS_AMP_SDLL_UPDATE_CNTL(AMP_CA), dcs_params.casdllupdatectrl);
dcs_reg_write_all_chan(rDCS_AMP_SDLL_UPDATE_CNTL(AMP_DQ0), dcs_params.dqsdllupdatectrl);
dcs_reg_write_all_chan(rDCS_AMP_SDLL_UPDATE_CNTL(AMP_DQ1), dcs_params.dqsdllupdatectrl);
dcs_reg_write_all_chan(rDCS_AMP_RDSDLLCTRL(AMP_DQ0), dcs_params.rdsdllctrl_step2);
dcs_reg_write_all_chan(rDCS_AMP_RDSDLLCTRL(AMP_DQ1), dcs_params.rdsdllctrl_step2);
dcs_reg_poll_all_chan(rDCS_AMP_RDSDLLCTRL(AMP_DQ0), dcs_params.rdsdllctrl_step2 & 0x7, 0x0);
dcs_reg_poll_all_chan(rDCS_AMP_RDSDLLCTRL(AMP_DQ1), dcs_params.rdsdllctrl_step2 & 0x7, 0x0);
dcs_reg_write_all_chan(rDCS_AMP_WRDQDQSSDLLCTRL(AMP_DQ0), dcs_params.wrdqdqssdllctrl_step2);
dcs_reg_write_all_chan(rDCS_AMP_WRDQDQSSDLLCTRL(AMP_DQ1), dcs_params.wrdqdqssdllctrl_step2);
dcs_reg_poll_all_chan(rDCS_AMP_WRDQDQSSDLLCTRL(AMP_DQ0), dcs_params.wrdqdqssdllctrl_step2 & 0x7, 0x0);
dcs_reg_poll_all_chan(rDCS_AMP_WRDQDQSSDLLCTRL(AMP_DQ1), dcs_params.wrdqdqssdllctrl_step2 & 0x7, 0x0);
dcs_reg_write_all_chan(rDCS_AMP_CAWRLVLSDLLCODE, dcs_params.cawrlvlsdllcode);
dcs_reg_poll_all_chan(rDCS_AMP_CAWRLVLSDLLCODE, dcs_params.cawrlvlsdllcode & 0x300, 0x000);
if (!izFPGA)
for(i = AMP_CA ; i < DCS_AMP_NUM_PHYS; i++)
dcs_reg_write_all_chan(rDCS_AMP_DLLLOCKTIM(i), dcs_params.dlllocktim);
if(dcs_cfg.chipID == 0x8000 && dcs_cfg.chipRev >= CHIP_REVISION_B0) {
dcs_reg_write_all_chan(rDCS_AMP_DQSPDENALWYSON(AMP_DQ0), 0x00000001);
dcs_reg_write_all_chan(rDCS_AMP_DQSPDENALWYSON(AMP_DQ1), 0x00000001);
}
if((dcs_params.supported_freqs & DCS_FREQ(1)) != 0)
dcs_reg_write_all_chan(rDCS_AMP_DFICALTIMING, dcs_params.dficaltiming);
if (dcs_cfg.chipRev < CHIP_REVISION_B0)
{
for(i = 1; i < DCS_FREQUENCY_SLOTS; i++)
dcs_reg_write_all_chan(rDCS_AMPCA_DFICALTIMING_F(i), dcs_params.freq[i].cadficaltiming);
for(i = 0; i < DCS_FREQUENCY_SLOTS; i++) {
dcs_reg_write_all_chan(rDCS_AMPDQ_DFICALTIMING_F(AMP_DQ0, i), dcs_params.freq[i].dqdficaltiming);
dcs_reg_write_all_chan(rDCS_AMPDQ_DFICALTIMING_F(AMP_DQ1, i), dcs_params.freq[i].dqdficaltiming);
}
}
else
{
dcs_reg_write_all_chan(rDCS_AMPCA_DFICALTIMING_F(1), 0x04000710);
dcs_reg_write_all_chan(rDCS_AMPCA_DFICALTIMING_F(2), 0x04000710);
dcs_reg_write_all_chan(rDCS_AMPCA_DFICALTIMING_F(3), 0x04000510);
dcs_reg_write_all_chan(rDCS_AMPDQ_DFICALTIMING_F(AMP_DQ0, 0), 0x06020704);
dcs_reg_write_all_chan(rDCS_AMPDQ_DFICALTIMING_F(AMP_DQ0, 1), 0x04020702);
dcs_reg_write_all_chan(rDCS_AMPDQ_DFICALTIMING_F(AMP_DQ0, 2), 0x04020702);
dcs_reg_write_all_chan(rDCS_AMPDQ_DFICALTIMING_F(AMP_DQ0, 3), 0x04020504);
dcs_reg_write_all_chan(rDCS_AMPDQ_DFICALTIMING_F(AMP_DQ1, 0), 0x06020704);
dcs_reg_write_all_chan(rDCS_AMPDQ_DFICALTIMING_F(AMP_DQ1, 1), 0x04020702);
dcs_reg_write_all_chan(rDCS_AMPDQ_DFICALTIMING_F(AMP_DQ1, 2), 0x04020702);
dcs_reg_write_all_chan(rDCS_AMPDQ_DFICALTIMING_F(AMP_DQ1, 3), 0x04020504);
dcs_reg_write_all_chan(rDCS_AMPCA_DFICALTIMING_RDDQCAL2, 0x00000019);
}
dcs_reg_write_all_chan(rDCS_AMP_MDLLCODE_CAP_CNTL(AMP_DQ0), 0x00000002);
dcs_reg_write_all_chan(rDCS_AMP_MDLLCODE_CAP_CNTL(AMP_DQ1), 0x00000002);
dcs_reg_write_all_chan(rDCS_AMP_RDWRDQCALTIMING_F(0), dcs_params.rdwrdqcaltiming_f0);
if (dcs_cfg.chipRev < CHIP_REVISION_B0)
dcs_reg_write_all_chan(rDCS_AMP_RDWRDQCALSEGLEN_F(0), dcs_params.rdwrdqcalseglen_f0);
else
dcs_reg_write_all_chan(rDCS_AMP_RDWRDQCALSEGLEN_F(0), 0x00040008);
dcs_reg_write_all_chan(rDCS_AMP_RDWRDQCALTIMING_F(1), dcs_params.rdwrdqcaltiming_f1);
dcs_reg_write_all_chan(rDCS_AMP_RDWRDQCALSEGLEN_F(1), dcs_params.rdwrdqcalseglen_f1);
dcs_reg_write_all_chan(rDCS_AMP_RDWRDQCALTIMING_F(3), dcs_params.rdwrdqcaltiming_f3);
dcs_reg_write_all_chan(rDCS_AMP_HWRDWRDQCALTIMINGCTRL(1), dcs_params.rdwrdqcaltimingctrl1);
dcs_reg_write_all_chan(rDCS_AMP_HWRDWRDQCALTIMINGCTRL(2), dcs_params.rdwrdqcaltimingctrl2);
dcs_reg_write_all_chan(rDCS_AMP_HWRDDQCALPATPRBS4I, dcs_params.rddqcalpatprbs4i);
dcs_reg_write_all_chan(rDCS_AMP_HWWRDQCALPATPRBS4I, dcs_params.wrdqcalpatprbs4i);
dcs_reg_write_all_chan(rDCS_AMP_HWWRDQCALPATPRBS7(0), 0x87654321);
dcs_reg_write_all_chan(rDCS_AMP_HWWRDQCALPATPRBS7(1), 0xcdedcba9);
dcs_reg_write_all_chan(rDCS_AMP_HWWRDQCALPATPRBS7(2), 0x456789ab);
dcs_reg_write_all_chan(rDCS_AMP_HWWRDQCALPATPRBS7(3), 0x5fa63123);
dcs_reg_write_all_chan(rDCS_AMP_HWWRDQCALPATINVERTMASK, 0x55550000);
dcs_reg_write_all_chan(rDCS_AMP_RDDQCALWINDOW_F(0), dcs_params.freq[0].rddqcalwindow);
dcs_reg_write_all_chan(rDCS_AMP_WRDQCALWINDOW_F(0), dcs_params.freq[0].wrdqcalwindow);
dcs_reg_write_all_chan(rDCS_AMP_RDDQCALWINDOW_F(1), dcs_params.freq[1].rddqcalwindow);
dcs_reg_write_all_chan(rDCS_AMP_WRDQCALWINDOW_F(1), dcs_params.freq[1].wrdqcalwindow);
dcs_reg_write_all_chan(rDCS_AMP_MAXRDDQS_SDLL_MULFACTOR, dcs_params.maxrddqssdllmulfactor);
dcs_reg_write_all_chan(rDCS_AMP_MAXWRDQS_SDLL_MULFACTOR, dcs_params.maxwrdqssdllmulfactor);
// These register writes to be skipped for Maui A0/A1
if((dcs_cfg.chipID != 0x8000) || (dcs_cfg.chipID == 0x8000 && dcs_cfg.chipRev >= CHIP_REVISION_B0)) {
dcs_reg_write_all_chan(rDCS_AMPDQ_RDDQSMULFACTOR(AMP_DQ0), 0x20181000);
dcs_reg_write_all_chan(rDCS_AMPDQ_RDDQSMULFACTOR(AMP_DQ1), 0x20181000);
}
for(i = 0; i < DCS_FREQUENCY_SLOTS; i++) {
dcs_reg_write_all_chan(rDCS_AMP_RDCAPCFG_FREQ(AMP_DQ0, i), dcs_params.freq[i].rdcapcfg);
dcs_reg_write_all_chan(rDCS_AMP_RDCAPCFG_FREQ(AMP_DQ1, i), dcs_params.freq[i].rdcapcfg);
}
if (!izFPGA) {
for(i = AMP_CA ; i < DCS_AMP_NUM_PHYS; i++)
dcs_reg_write_all_chan(rDCS_AMP_DLLUPDTCTRL(i), dcs_params.dllupdtctrl1);
}
dcs_reg_write_all_chan(rDCS_AMP_DLLUPDTINTVL(AMP_CA), dcs_params.dllupdtintvl);
dcs_reg_write_all_chan(rDCS_AMP_DLLUPDTINTVL(AMP_DQ0), dcs_params.dllupdtintvl);
dcs_reg_write_all_chan(rDCS_AMP_DLLUPDTINTVL(AMP_DQ1), dcs_params.dllupdtintvl);
for(i = AMP_DQ0 ; i < DCS_AMP_NUM_PHYS; i++)
dcs_reg_write_all_chan(rDCS_AMP_DLLEN(i), 0x00000100);
dcs_reg_write_all_chan(rDCS_AMP_DCCCONTROL, dcs_params.dcccontrol);
dcs_reg_write_all_chan(rDCS_AMP_DCCTIMER, 0x00000190);
dcs_reg_write_all_chan(rDCS_AMP_HWWRDQCALDYNHALFCLKDLYCTRL, 0x00000001);
// AMPH configuration
dcs_reg_write_all_chan(rDCS_AMPH_CB_WKPUPD, 0);
dcs_reg_write_all_chan(rDCS_AMPH_CB_DRIVESTR, dcs_params.cbdrivestr);
dcs_reg_write_all_chan(rDCS_AMPH_CB_IOCTL, dcs_params.cbioctl);
dcs_reg_write_all_chan(rDCS_AMPH_CK_WKPUPD, 0);
dcs_reg_write_all_chan(rDCS_AMPH_CK_ZDETBIASEN, 0);
dcs_reg_write_all_chan(rDCS_AMPH_CK_DRIVESTR, dcs_params.ckdrivestr);
dcs_reg_write_all_chan(rDCS_AMPH_CK_IOCTL, dcs_params.ckioctl);
dcs_reg_write_all_chan(rDCS_AMPH_B0_DRIVESTR, dcs_params.b0drivestr);
dcs_reg_write_all_chan(rDCS_AMPH_B0_WKPUPD, 0);
dcs_reg_write_all_chan(rDCS_AMPH_B0_IOCTL, dcs_params.b0ioctl);
dcs_reg_write_all_chan(rDCS_AMPH_B0_ODT, dcs_params.b0odt);
dcs_reg_write_all_chan(rDCS_AMPH_B0_ODTCTRL, dcs_params.b0odtctrl);
dcs_reg_write_all_chan(rDCS_AMPH_B1_DRIVESTR, dcs_params.b1drivestr);
dcs_reg_write_all_chan(rDCS_AMPH_B1_ODTCTRL, dcs_params.b1odtctrl);
dcs_reg_write_all_chan(rDCS_AMPH_B1_WKPUPD, 0);
dcs_reg_write_all_chan(rDCS_AMPH_B1_IOCTL, dcs_params.b1ioctl);
dcs_reg_write_all_chan(rDCS_AMPH_B1_ODT, dcs_params.b1odt);
dcs_reg_write_all_chan(rDCS_AMPH_DQS0_WKPUPD, 0x00000782);
dcs_reg_write_all_chan(rDCS_AMPH_DQS0_DRIVESTR, dcs_params.dqs0drivestr);
dcs_reg_write_all_chan(rDCS_AMPH_DQS0_IOCTL, dcs_params.dqs0ioctl);
dcs_reg_write_all_chan(rDCS_AMPH_DQS0_ODT, dcs_params.dqs0odt);
dcs_reg_write_all_chan(rDCS_AMPH_DQS0_ZDETBIASEN, dcs_params.dqs0zdetbiasen);
dcs_reg_write_all_chan(rDCS_AMPH_DQS0_ODTCTRL, dcs_params.dqs0odtctrl);
dcs_reg_write_all_chan(rDCS_AMPH_DQS1_WKPUPD, 0x00000782);
dcs_reg_write_all_chan(rDCS_AMPH_DQS1_DRIVESTR, dcs_params.dqs1drivestr);
dcs_reg_write_all_chan(rDCS_AMPH_DQS1_IOCTL, dcs_params.dqs1ioctl);
dcs_reg_write_all_chan(rDCS_AMPH_DQS1_ODT, dcs_params.dqs1odt);
dcs_reg_write_all_chan(rDCS_AMPH_DQS1_ZDETBIASEN, dcs_params.dqs1zdetbiasen);
dcs_reg_write_all_chan(rDCS_AMPH_DQS1_ODTCTRL, dcs_params.dqs1odtctrl);
dcs_reg_write_all_chan(rDCS_AMPH_DBG_REG0, 0x00000000);
dcs_reg_write_all_chan(rDCS_AMPH_ZCAL_FSM(1), dcs_params.zcalfsm1);
dcs_reg_write_all_chan(rDCS_AMPH_ZCAL_FSM(0), dcs_params.zcalfsm0);
if (dcs_cfg.chipRev < CHIP_REVISION_B0)
dcs_reg_write_all_chan(rDCS_AMPH_SPARE(0), dcs_params.spare0);
else
dcs_reg_write_all_chan(rDCS_AMPH_SPARE(0), 0x00000816);
for(i = AMP_CA ; i < DCS_AMP_NUM_PHYS; i++)
dcs_reg_write_all_chan(rDCS_AMP_AMPINIT(i), 0x00000001);
if (dcs_cfg.chipRev < CHIP_REVISION_B0)
dcs_reg_write_all_chan(rDCS_AMP_DFICALTIMING, dcs_params.dficaltiming);
else
{
dcs_reg_write_all_chan(rDCS_AMP_DFICALTIMING, 0x06001604);
dcs_reg_write_all_chan(rDCS_AMPDQ_DFICALTIMING_F(AMP_DQ0, 0), 0x06021604);
dcs_reg_write_all_chan(rDCS_AMPDQ_DFICALTIMING_F(AMP_DQ1, 0), 0x06021604);
}
dcs_reg_write_all_chan(rDCS_AMP_HWRDDQCALTVREF, dcs_params.hwrddqcaltvref);
}
//================================================================================
// Step 3: Self-Refresh Exit
//================================================================================
void dcs_init_Self_Refresh_Exit_a(void)
{
// Wait 5 us after Impedence Calibration to avoid McPhyPending
// preventing the SRFSM from exiting SR.
dcs_spin(5, "after Imp. Cal.");
dcs_reg_write_all_chan(rDCS_MCU_AREFPARAM, dcs_params.arefparam);
for(int i = 0; i < DCS_FREQUENCY_SLOTS; i++)
dcs_reg_write_all_chan(rDCS_MCU_AUTOREF_FREQ(i), dcs_params.freq[i].autoref2);
dcs_reg_write_all_chan(rDCS_MCU_AUTOREF_PARAMS, dcs_params.autoref_params2);
dcs_reg_write_all_chan(rDCS_MCU_ODTSZQC, dcs_params.odtszqc);
// M8 Bug radar #20346417, two writes to ensure propogation
dcs_reg_write_all_chan(rDCS_MCU_LONGSR, dcs_params.longsr);
dcs_reg_write_all_chan(rDCS_MCU_LONGSR, dcs_params.longsr);
dcs_reg_write_all_chan(rDCS_MCU_MCPHYUPDTPARAM, 0x15030004);
}
//========================================
// Caller Code should:
// - Change Frequency to 50MHz
//========================================
void dcs_init_Self_Refresh_Exit_b(void)
{
dcs_reg_write_all_chan(rDCS_MCU_AMCCTRL, 0x00000003);
if (!izFPGA) {
dcs_reg_write_all_chan(rDCS_AMP_IMPCALCMD, 0x00000001);
dcs_reg_poll_all_chan(rDCS_AMP_IMPCALCMD, 0x01, 0x00);
}
if (izResume)
dcs_enable_autorefresh();
dcs_spin(2200, "After Enable Auto-Refresh");
if((dcs_cfg.chipID != 0x8000) || (dcs_cfg.chipID == 0x8000 && dcs_cfg.chipRev >= CHIP_REVISION_B0)) {
dcs_reg_write_all_chan(rDCS_MCU_FREQCHNGCTL, dcs_params.freqchngctl_step3);
dcs_reg_poll_all_chan(rDCS_MCU_FREQCHNGCTL, 0x10000, 0x00000);
dcs_spin(2, "After SoC Update");
}
// Resume-Boot and Cold-Boot use different Exit commands for Self-Refresh
// Issue self-refresh exit cmd for resume boot with MPC
int n = (izColdBoot)? 0x00000000:0x00004000;
// Issue self-refresh exit cmd for resume boot with MPC
dcs_reg_write_all_chan(rDCS_MCU_MRINITCMD_0, n);
dcs_reg_write_all_chan(rDCS_MCU_MRINITCMD_0, n | 0x1);
dcs_reg_poll_all_chan(rDCS_MCU_MRINITCMD_0, 0x01, 0x00);
dcs_spin(2, NULL);
dcs_reg_write(rGLBTIMER_CHEN, (1 << dcs_cfg.num_dcs) - 1);
}
//================================================================================
// Step 4: DRAM Reset, ZQ Calibration & Configuration (cold boot only)
//================================================================================
void dcs_init_ZQ_Cal_Cfg(void)
{
// ZQ calibration START MPC cmd
dcs_mrcmd(MR_MPC, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x0, 0x4f);
// wait 1us for tZQCAL
dcs_spin(1, "tZQCAL");
// ZQ calibration LATCH MPC cmd
dcs_mrcmd(MR_MPC, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x0, 0x51);
// wait 10ns for tZQLAT
dcs_spin(1, "tZQLAT");
if (izColdBoot) {
// MR2 register (read/write latency)
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x2, 0x0);
// MR1 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x1, 0x8e);
// MR3 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x3, dcs_params.mr3cmd);
// MR22 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x16, 0x0);
// MR11 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0xb, 0x0);
// MR13 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0xd, dcs_params.mr13cmd);
// MR12 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0xc, 0x59);
// MR14 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0xe, 0x59);
// MR23 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x17, 0x80);
uint32_t patinvertmask = (DCS_REG_READ_CH(0, rDCS_AMP_HWRDDQCALPATPRBS4I) >> 16) & 0xffff;
uint32_t prbs = DCS_REG_READ_CH(0, rDCS_AMP_HWWRDQCALPATPRBS4I);
// MR15 register
dcs_mrcmd(MR_MPC, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0xf, patinvertmask & 0xff);
// MR20 register
dcs_mrcmd(MR_MPC, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x14, (patinvertmask >> 8) & 0xff);
// MR32 register
dcs_mrcmd(MR_MPC, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x20, prbs & 0xff);
// MR40 register
dcs_mrcmd(MR_MPC, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x28, (prbs >> 8) & 0xff);
}
}
//================================================================================
// Step 5a: AddrConfig Configuration
//================================================================================
void dcs_init_AddrCfg_Cfg(void)
{
dcs_reg_write(rAMCC_ADDRCFG_ADDR, dcs_params.addrcfg);
#if NUM_AMCCS == 2
dcs_reg_write(rAMCC1_ADDRCFG_ADDR, dcs_params.addrcfg);
#endif
}
//========================================
// Caller Code should:
// - Use MR Cmds to Query the Device
//========================================
//================================================================================
// Step 5b: Total Mem Size Config
//================================================================================
void dcs_init_TotalSize_Cfg(uint32_t total_size_Mbytes)
{
dbgprintf(DCS_DBG_ASSESS_CONFIG, "Memory_size: %llu bytes\n",
(((uint64_t)total_size_Mbytes) * MEG * NUM_AMCCS));
// (Units of 128 MBs in the register)
dcs_reg_write(rAMCC_DRAMACCCTRL_ADDR, ((total_size_Mbytes / NUM_AMCCS) / DCS_NUM_MEG_IN_DRAM_BLK) - 1);
dcs_reg_write(rAMCC_MCCCHNLDEC_ADDR, dcs_params.chnldec);
#if NUM_AMCCS == 2
dcs_reg_write(rAMCC1_DRAMACCCTRL_ADDR, ((total_size_Mbytes / NUM_AMCCS) / DCS_NUM_MEG_IN_DRAM_BLK) - 1);
dcs_reg_write(rAMCC1_MCCCHNLDEC_ADDR, dcs_params.chnldec);
#endif
dbgprintf(DCS_DBG_ASSESS_CONFIG, "rAMCC_DRAMACCCTRL: 0x%08x\n", rAMCC_DRAMACCCTRL);
const struct dcs_memory_device_info *dev_info = dcs_get_memory_device_info();
if((dev_info->vendor_id == JEDEC_LPDDR4_MANUF_ID_SAMSUNG) && (dev_info->rev_id == 5) && (dev_info->rev_id2 <= 1))
apply_samsung_workaround = true;
if(apply_samsung_workaround) {
dcs_reg_write_all_chan(rDCS_AMP_VREF_F(AMP_DQ0, 0), 0x00d800d8);
dcs_reg_write_all_chan(rDCS_AMP_VREF_F(AMP_DQ1, 0), 0x00d800d8);
dcs_reg_write_all_chan(rDCS_AMP_VREF_F(AMP_DQ0, 1), 0x00d800d8);
dcs_reg_write_all_chan(rDCS_AMP_VREF_F(AMP_DQ1, 1), 0x00d800d8);
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x3, 0xf2);
dcs_mrcmd(MR_MPC, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x0, 0x4f);
dcs_spin(1, " For tZQCAL");
dcs_mrcmd(MR_MPC, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x0, 0x51);
dcs_reg_write_all_chan(rDCS_MCU_FREQCHNGCTL_FREQ(2, 0), 0xb203330b);
dcs_reg_write_all_chan(rDCS_MCU_FREQCHNGCTL_FREQ(4, 0), 0x00000316);
dcs_reg_write_all_chan(rDCS_MCU_FREQCHNGCTL_FREQ(2, 3), 0xf203000b);
dcs_reg_write_all_chan(rDCS_AMPH_CB_IMPCTL, 0x01001c2b);
dcs_reg_write_all_chan(rDCS_AMPH_B0_ODT, 0x01c00339);
dcs_reg_write_all_chan(rDCS_AMPH_B1_ODT, 0x01c00339);
dcs_reg_write_all_chan(rDCS_AMPH_DQS0_ODT, 0x01c00339);
dcs_reg_write_all_chan(rDCS_AMPH_DQS1_ODT, 0x01c00339);
}
}
//================================================================================
// Step 6: Switch from boot-clock speed to normal operation speed
//================================================================================
void dcs_init_Reenable_AMC_Scheduler(void)
{
// Wait 5 us before freq change to make sure all refreshes have been flushed
dcs_spin(5, "After Refresh");
// Enable (again) the AMC Scheduler
dcs_reg_write_all_chan(rDCS_MCU_AMCCTRL, 0x00000003);
}
//================================================================================
// Step 7: Setup registers for CA calibration for bucket 1
//================================================================================
void dcs_init_CA_Cal_Setup_Freq1(void)
{
// MR13 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0xd, dcs_params.mr13cmd_step7);
if (izColdBoot) {
if (izFPGA) {
// MR11 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0xb, 0x00);
} else {
// MR2 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x2, 0x52);
// MR1 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x1, 0xae);
// MR3 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x3, dcs_params.mr3cmd_step7);
// MR22 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x16, dcs_params.mr22cmd);
// MR11 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0xb, dcs_params.mr11cmd);
// MR12 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0xc, 0x11);
// MR14 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0xe, 0x11);
}
dcs_reg_write_all_chan(rDCS_AMP_CAWRLVLSDLLCODE, 0x00000200);
dcs_reg_poll_all_chan(rDCS_AMP_CAWRLVLSDLLCODE, 0x0200, 0x0000);
}
}
//================================================================================
// Step 8: AMP Dynamic CA Vref Timing Calibration at Vmin 800MHz
//================================================================================
void dcs_init_CA_Cal_Freq1(void)
{
// Nothing to be done at this step for cold boot
}
//================================================================================
// Step 9: Setup registers for DQ calibration for bucket 1
//================================================================================
void dcs_init_DQ_Cal_Setup_Freq1_a(void)
{
int i;
if (izColdBoot) {
// MR13 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0xd, dcs_params.mr13cmd_step9);
}
dcs_spin(1, NULL);
if(izResume) {
dcs_reg_write_all_chan(rDCS_MCU_PWRMNGTEN, 0x00000002);
dcs_reg_write_all_chan(rDCS_MCU_FREQCHNGCTL, 0x01008888);
for(i = AMP_DQ0 ; i < DCS_AMP_NUM_PHYS; i++)
dcs_reg_write_all_chan(rDCS_AMP_WRDQDQSSDLLCTRL(i), 0xFF00000C);
for(i = AMP_CA ; i < DCS_AMP_NUM_PHYS; i++)
dcs_reg_write_all_chan(rDCS_AMP_SDLL_UPDATE_DEFER_EN(i), 0x00000000);
for(i = AMP_DQ0; i < DCS_AMP_NUM_PHYS; i++)
dcs_reg_write_all_chan(rDCS_AMP_MDLLOVRRD(i), 0x00000000);
}
}
// Caller code should change frequency to bucket 1
void dcs_init_DQ_Cal_Setup_Freq1_b(void)
{
if (izColdBoot) {
if((dcs_cfg.chipID != 0x8000) || (dcs_cfg.chipID == 0x8000 && dcs_cfg.chipRev >= CHIP_REVISION_B0)) {
dcs_reg_write_all_chan(rDCS_MCU_FREQCHNGCTL, dcs_params.freqchngctl_step9);
dcs_reg_poll_all_chan(rDCS_MCU_FREQCHNGCTL, 0x10000, 0x00000);
// Wait 2us for the soc update to finish
dcs_spin(2, NULL);
}
}
}
//================================================================================
// Step 10: PHY write DQ calibration
//================================================================================
void dcs_init_wrdq_skew(void)
{
dcs_reg_write_all_chan(rDCS_AMP_DQSDQ_SKEWCTL(AMP_DQ0), 0x06000000);
dcs_reg_write_all_chan(rDCS_AMP_DQSDQ_SKEWCTL(AMP_DQ1), 0x06000000);
}
//================================================================================
// Step 11: Setup registers for CA calibration for bucket 0
//================================================================================
void dcs_init_CA_Cal_Setup_Freq0(void)
{
if (izColdBoot) {
if(dcs_cfg.chipID == 0x8000 && dcs_cfg.chipRev >= CHIP_REVISION_B0) {
dcs_reg_write_all_chan(rDCS_AMP_DQFLTCTRL(AMP_DQ0), 0x00000000);
dcs_reg_write_all_chan(rDCS_AMP_DQFLTCTRL(AMP_DQ1), 0x00000000);
}
// MR13 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x0d, dcs_params.mr13cmd_step11);
if (!izFPGA) {
// MR2 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x02, dcs_params.mr2cmd_step11);
// MR1 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x01, dcs_params.mr1cmd_step11);
// MR3 register
if(apply_samsung_workaround)
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x03, 0xb2);
else
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x03, dcs_params.mr3cmd_step11);
}
if(apply_samsung_workaround) {
// MR22 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x16, 0x03);
// MR11 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x0b, 0x33);
} else {
// MR22 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x16, dcs_params.mr22cmd_step11);
// MR11 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x0b, (izFPGA) ? 0x00 : dcs_params.mr11cmd_step11);
}
// MR12 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x0c, dcs_params.mr12cmd_step11);
// MR14 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x0e, dcs_params.mr14cmd_step11);
if((dcs_params.supported_freqs & DCS_FREQ(1)) == 0) {
dcs_reg_write_all_chan(rDCS_AMP_CAWRLVLSDLLCODE, 0x00000200);
dcs_reg_poll_all_chan(rDCS_AMP_CAWRLVLSDLLCODE, 0x200, 0x000);
}
}
}
//================================================================================
// Step 12: AMP Dynamic CA Timing Calibration
//================================================================================
//================================================================================
// Step 13: Setup registers for DQ calibration for bucket 0
//================================================================================
void dcs_init_DQ_Cal_Setup_Freq0_a(void)
{
if (izColdBoot) {
// MR13 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x0d, dcs_params.mr13cmd_step13);
// Wait 1 us
dcs_spin(1, NULL);
}
}
void dcs_init_DQ_Cal_Setup_Freq0_b(void)
{
if (izColdBoot) {
if((dcs_cfg.chipID != 0x8000) || (dcs_cfg.chipID == 0x8000 && dcs_cfg.chipRev >= CHIP_REVISION_B0)) {
dcs_reg_write_all_chan(rDCS_MCU_FREQCHNGCTL, 0x00010000);
dcs_reg_poll_all_chan(rDCS_MCU_FREQCHNGCTL, 0x10000, 0x00000);
// Wait 2us for the soc update to finish
dcs_spin(2, NULL);
}
}
}
//================================================================================
// Step 14: AMP Dynamic DQ Calibration
//================================================================================
void dcs_init_post_wrlvl(void)
{
if(dcs_cfg.chipID == 0x8000 && dcs_cfg.chipRev >= CHIP_REVISION_B0) {
dcs_reg_write_all_chan(rDCS_AMP_DQFLTCTRL(AMP_DQ0), 0x00000010);
dcs_reg_write_all_chan(rDCS_AMP_DQFLTCTRL(AMP_DQ1), 0x00000010);
}
if (!izFPGA)
{
dcs_reg_write_all_chan(rDCS_AMPH_DQS0_WKPUPD, dcs_params.dqs0wkpupd);
dcs_reg_write_all_chan(rDCS_AMPH_DQS1_WKPUPD, dcs_params.dqs1wkpupd);
}
}
//================================================================================
// Step 15: Setup Registers for Boot
//================================================================================
void dcs_init_Reg_for_Boot(void)
{
if (dcs_cfg.chipRev >= CHIP_REVISION_B0)
dcs_reg_write_all_chan(rDCS_AMPH_SPARE(0), 0xc16);
#ifndef DCS_RUN_AT_50MHZ
if (izColdBoot) {
// MR13 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x0d, dcs_params.mr13cmd_step15);
}
#endif
if(izFPGA && !(dcs_params.supported_freqs & DCS_FREQ(1)))
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x0d, 0x50);
// Wait 1 us
dcs_spin(1, NULL);
if (izColdBoot) {
dcs_reg_write_all_chan(rDCS_MCU_FREQCHNGCTL, dcs_params.freqchngctl_step15);
dcs_reg_write_all_chan(rDCS_AMP_WRDQDQSSDLLCTRL(AMP_DQ0), 0xff000008);
dcs_reg_write_all_chan(rDCS_AMP_WRDQDQSSDLLCTRL(AMP_DQ1), 0xff000008);
#if !DCS_DO_CALIBRATION
// skip these for all silicon targets, where calibration is performed, also skip for any Maui A1 target
if((dcs_cfg.chipID != 0x8000) || (dcs_cfg.chipID == 0x8000 && dcs_cfg.chipRev >= CHIP_REVISION_B0)) {
dcs_reg_write_all_chan(rDCS_AMP_RDDQSDLL_DLYSEL(AMP_DQ0), 0x00000000);
dcs_reg_write_all_chan(rDCS_AMP_RDDQSDLL_DLYSEL(AMP_DQ1), 0x00000000);
dcs_reg_write_all_chan(rDCS_AMP_RDSDLLCTRL(AMP_DQ0), dcs_params.rdsdllctrl_step15);
dcs_reg_write_all_chan(rDCS_AMP_RDSDLLCTRL(AMP_DQ1), dcs_params.rdsdllctrl_step15);
dcs_reg_poll_all_chan(rDCS_AMP_RDSDLLCTRL(AMP_DQ0), dcs_params.rdsdllctrl_step15 & 0x7, 0x0);
dcs_reg_poll_all_chan(rDCS_AMP_RDSDLLCTRL(AMP_DQ1), dcs_params.rdsdllctrl_step15 & 0x7, 0x0);
}
#endif
}
if(!izFPGA)
{
dcs_reg_write_all_chan(rDCS_AMP_HWRDWRDQCALFULLSCANEN, 0x00000000);
dcs_reg_write_all_chan(rDCS_AMP_HWRDWRDQCALFULLSCANEN, 0x00000003);
}
dcs_reg_write_all_chan(rDCS_AMP_HWRDDQCALVREFCONTROL, 0x01D0B061);
dcs_reg_write_all_chan(rDCS_AMP_HWWRDQCALVREFCONTROL, 0x02200061);
}
//================================================================================
// Step 16: Enable Other Features
//================================================================================
void dcs_init_MoreFeatures(void)
{
dcs_reg_write_all_chan(rDCS_MCU_AREFPARAM, dcs_params.arefparam);
dcs_reg_write_all_chan(rDCS_MCU_ODTSZQC, dcs_params.odtszqc2);
dcs_reg_write_all_chan(rDCS_MCU_QBREN, dcs_params.qbren_step16);
if (izColdBoot)
dcs_enable_autorefresh();
dcs_reg_write_all_chan(rDCS_AMPH_B0_DYN_ISEL_ASRTIME, dcs_params.b0dyniselasrtime);
dcs_reg_write_all_chan(rDCS_AMPH_B0_DYN_ISEL, dcs_params.b0dynisel);
dcs_reg_write_all_chan(rDCS_AMPH_B1_DYN_ISEL, dcs_params.b1dynisel);
}
//================================================================================
// Step 17: Enable Fast Critical Word Forwarding Feature
//================================================================================
void dcs_init_Fast_Critical_Word_Forwarding(void)
{
dcs_reg_write_all_chan(rDCS_MCU_QBRPARAM, dcs_params.qbrparam);
dcs_reg_write_all_chan(rDCS_MCU_QBREN, dcs_params.qbren);
dcs_reg_write(rAMCC_MCCGEN_ADDR, dcs_params.mccgen);
dcs_reg_write(rAMCC_MCC0QPROPCTRL_ADDR, 0x300011a2);
dcs_reg_write(rAMCC_MCC1QPROPCTRL_ADDR, 0x300011a2);
#if NUM_AMCCS == 2
dcs_reg_write(rAMCC1_MCCGEN_ADDR, dcs_params.mccgen);
dcs_reg_write(rAMCC1_MCC0QPROPCTRL_ADDR, 0x300011a2);
dcs_reg_write(rAMCC1_MCC1QPROPCTRL_ADDR, 0x300011a2);
#endif // #if NUM_AMCCS == 2
}
//================================================================================
// Step 18: Enable Power- and Clock-Gating Features; Config MCC and Global Timers
//================================================================================
void dcs_init_Gating_Global_Timers(void)
{
dcs_reg_write_all_chan(rDCS_AMP_AMPCLK(AMP_CA), dcs_params.caampclk);
dcs_reg_write_all_chan(rDCS_AMP_AMPCLK(AMP_DQ0), dcs_params.dqampclk);
dcs_reg_write_all_chan(rDCS_AMP_AMPCLK(AMP_DQ1), dcs_params.dqampclk);
dcs_reg_write_all_chan(rDCS_SPLLCTRL_MDLLPWRDNCFG(0), 0x00000001);
dcs_reg_write_all_chan(rDCS_MCU_PWRMNGTEN, dcs_params.pwrmngten);
// Global Timer Setup
dcs_reg_write(rGLBTIMER_PMGRWAKEUPCFG, 0x0001ff);
dcs_reg_write(rGLBTIMER_PREFREQ2ALLBANKDLY(0), 0x00f000f0);
dcs_reg_write(rGLBTIMER_PREFREQ2ALLBANKDLY(1), 0x00f000f0);
dcs_reg_write(rGLBTIMER_PREFREQCHNG2FREQCHNGDLY(0), 0x02400240);
dcs_reg_write(rGLBTIMER_PREFREQCHNG2FREQCHNGDLY(1), 0x02400240);
dcs_reg_write(rGLBTIMER_CALSEG2ALLBANK(0), 0x00fa0120);
dcs_reg_write(rGLBTIMER_ALLBANK2CALSEG(0), 0x00fa0120);
dcs_reg_write(rGLBTIMER_MDLLTIMER, 0x000bb8);
dcs_reg_write(rGLBTIMER_DCCTIMER, 0x000bb8);
dcs_reg_write(rGLBTIMER_MDLLVOLTRAMPTIMER, 0x00004b);
dcs_reg_write(rGLBTIMER_CTRLUPDMASKTIMER, 0x00000f);
// <rdar://problem/19573098> Elba A0: Samsung 20nm Rev0 LPDDR4 work-around(disable IDT cal)
//dcs_reg_write(rGLBTIMER_IDTTIMER, 0x007530); // 30000
dcs_reg_write(rGLBTIMER_RDCALTIMER, 0x002dc6bb);
dcs_reg_write(rGLBTIMER_WRCALTIMER, 0x002dc6c0);
// <rdar://problem/23244578> Elba: Samsung DRAM workaround: disable hw zqcal
if(!apply_samsung_workaround)
dcs_reg_write(rGLBTIMER_ZQCTIMER, 0x3d0900);
dcs_reg_write(rGLBTIMER_PERCAL_FREQCHNGTIMER, 0x000001);
dcs_reg_write(rGLBTIMER_IMPCALTIMER, 0x002ee0);
// Dynamic Clk & Power Gating
dcs_reg_write_all_chan(rDCS_MCU_AMCCLKPWRGATE, 0x050a0000);
}
//================================================================================
// Step 19: ODTS read & set interval for periodic MR4 on-die Temp sensor reading
//================================================================================
void dcs_init_ODTS(void)
{
uint8_t temp[16*8]; // Far more Channels/Ranks than we are likely ever to have/need
// INSTEAD OF: uint8_t temp[dcs_cfg.num_dcs * dcs_cfg.num_rank];
// MR4 read to bring memory out of self-refresh
dcs_mrcmd(MR_READ, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x4, (uintptr_t)temp);
// M8 Bug radar #20346417, two writes to ensure propogation
dcs_reg_write_all_chan(rDCS_MCU_ODTSZQC, dcs_params.odtszqc3);
dcs_reg_write_all_chan(rDCS_MCU_ODTSZQC, dcs_params.odtszqc3);
}
// <rdar://problem/23244578>: This function used in calibration code for Elba
bool shim_apply_samsung_workaround(void)
{
return apply_samsung_workaround;
}
//================================================================================
+889
View File
@@ -0,0 +1,889 @@
/*
* Copyright (C) 2014-2015 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.
*/
/*
* Init Sequence Library for use in:
* Driver for the LPDDR4 compatible DRAM Control Subsystem (DCS) block
*/
/*
Summary of Steps from the Spec (Spreadsheet)
+ (Aa) Steps 0,1,2,3a [need to identify parameterization]
+ (Ab) Step 3b [PMGR: set Freq to 50MHz & delay-wait]
+ (Ac) Steps 3c,4,5 [need to identify parameterization]
+ (B) Step 6 [Change Clk Speed]
+ (C) Step 7 [include delay-wait from early Step 8]
+ (D) Step 8a [Cal: CA 800MHz Vmin]
+ (E) Step 8b [Write Regs]
+ (F) Step 8c [Cal: CA 800MHz Vmin] (...again? should it be CS?)
+ (G) Step 8d [Write Regs]
+ (H) Step 9 [Write Regs]
+ (I) Step 10 [Cal: WrLvl, RdDq, WrDq 800MHz Vmin]
+ (J) Step 11 [Write Regs]
+ (K) Step 12 [Cal: CA 1200MHz Vnom]
+ (L) Step 13 [Write Regs]
+ (M) Step 14 [Cal: WrLvl, RdDq, WrDq 1200MHz Vmin]
+ (N) Steps 15,16,17,18,19,20 [need to identify parameterization]
Between these steps there is possibly a need/desire for:
- Frequency Changes (PMGR)
- PMU save/restore
- debug messages
- register dumps (DV, SiVal)
- anything else!
CONFIG Table:
Compile-Time Known:
Type of Execution Environment CoreOS, DV, SiVal
Type of Target SoC, FPGA, Palladium
ChipID 0x8000, 0x8001, etc.
Revision A0, B0, B1, etc.
Num DCS 4, 8, etc. (Derived...!)
Variant Flags Work-arounds, RADAR Ref., et al.
(Config Info know at Compile time can be subject to #if)
Run-Time Known:
Type of Init ColdBoot, AOP_DDR, AOP_AWAKE
Debug Flags Low-Level, Milestone, et al.
RegValue Table
Much like today's: various values for various registers
Sensitive to ChipID (also Target type?)
(Internal static alloc (Complete Table Fill-in within Init function):
Fill in Values (per ChipID/Rev & Target-type)
return pointer to caller
(Allows customization by caller before use)
TODO:
- Convert to using SPDS for register names, et al
*/
//================================================================================
// API Definitions
#include <drivers/dcs/dcs_init_lib.h>
extern dcs_config_t dcs_cfg;
extern dcs_config_params_t dcs_params;
#if izIBOOT
extern int debug_level_dcs;
#endif
void dcs_enable_autorefresh(void)
{
// Configure auto-refresh. Freq0 has the auto-refresh enable, so do it last.
dcs_reg_write_all_chan(rDCS_MCU_AREFEN_FREQ(3), 0x11100000);
dcs_reg_write_all_chan(rDCS_MCU_AREFEN_FREQ(2), 0x11000000);
dcs_reg_write_all_chan(rDCS_MCU_AREFEN_FREQ(1), 0x11110000);
dcs_reg_write_all_chan(rDCS_MCU_AREFEN_FREQ(0), 0x1111013f);
}
//================================================================================
// Implementing the Various Steps of the DCS Init, per Specification
// Based on AMC Init Spec (Spreadsheet)
// - Supporting Maui: Spec (v??)
//================================================================================
// Step 0: AMC Prolog
//================================================================================
void dcs_init_Prolog(void)
{
// NOTE: between the Compiler and the Optimization, this should vanish for non-FPGA builds
if (izFPGA && izColdBoot) {
dcs_reg_write_all_chan(rDCS_AMP_DRAM_RESETN(AMP_CA), 1);
delay_for_us(200);
dcs_reg_write_all_chan(rDCS_AMP_DRAM_RESETN(AMP_CA), 0);
delay_for_us(200);
dcs_reg_write_all_chan(rDCS_AMP_DRAM_RESETN(AMP_CA), 1);
delay_for_us(200);
}
}
//================================================================================
// Step 1: AMC Initial Configuration
//================================================================================
void dcs_init_AMC_Initial_Config(void)
{
uint32_t i,n;
// rdar://problem/19137387: this applies to Maui A1 and B0, as well as other SoCs before Cayman
dcs_reg_write(rAMCC_MCCCHNLDEC_ADDR, dcs_params.chnldec);
dcs_reg_write_all_chan(rDCS_SPLLCTRL_CHARGEPUMP, 0x00000068);
dcs_reg_write_all_chan(rDCS_SPLLCTRL_VCO, dcs_params.spllctrl_vco_1);
dcs_reg_write_all_chan(rDCS_SPLLCTRL_VCO, dcs_params.spllctrl_vco_2);
dcs_reg_write_all_chan(rDCS_SPLLCTRL_LDO, 0x00000004);
// This register write to be skipped for Maui A0/A1, but written to for B0 & later, and all other SoCs
if((dcs_cfg.chipID != 0x8000) || (dcs_cfg.chipID == 0x8000 && dcs_cfg.chipRev >= CHIP_REVISION_B0))
dcs_reg_write_all_chan(rDCS_SPLLCTRL_SPLLPWRDNCFG, 0x00000011);
for(i = 0; i < DCS_FREQUENCY_SLOTS; i++) {
for (n = 0; n < dcs_params.num_freqchngctl_regs; n++)
dcs_reg_write_all_chan(rDCS_MCU_FREQCHNGCTL_FREQ(n, i), dcs_params.freq[i].freqchngctl[n]);
// This register write to be skipped for Maui A0/A1, but written to for B0 & later, and all other SoCs
if((dcs_cfg.chipID != 0x8000) || (dcs_cfg.chipID == 0x8000 && dcs_cfg.chipRev >= CHIP_REVISION_B0))
dcs_reg_write_all_chan(rDCS_MCU_FREQCHNGTIM_FREQ(i), dcs_params.freq[i].freqchngtim);
}
dcs_reg_write_all_chan(rDCS_MCU_RWCFG, dcs_params.rwcfg);
for(i = AMP_CA ; i < DCS_AMP_NUM_PHYS; i++)
dcs_reg_write_all_chan(rDCS_AMP_DLLUPDTCTRL(i), dcs_params.dllupdtctrl);
dcs_reg_write_all_chan(rDCS_MCU_LAT_FREQ(0), dcs_params.freq[0].lat);
dcs_reg_write_all_chan(rDCS_MCU_LAT_FREQ(1), dcs_params.freq[1].lat);
for(i = 0; i < DCS_FREQUENCY_SLOTS; i++)
dcs_reg_write_all_chan(rDCS_MCU_PHYRDWRTIM_FREQ(i), dcs_params.freq[i].phyrdwrtim);
for(i = 0; i < DCS_FREQUENCY_SLOTS; i++) {
dcs_reg_write_all_chan(rDCS_MCU_CASPCH_FREQ(i), dcs_params.freq[i].caspch);
dcs_reg_write_all_chan(rDCS_MCU_ACT_FREQ(i), dcs_params.freq[i].act);
dcs_reg_write_all_chan(rDCS_MCU_AUTOREF_FREQ(i), dcs_params.freq[i].autoref);
dcs_reg_write_all_chan(rDCS_MCU_SELFREF_FREQ(i), dcs_params.freq[i].selfref);
if (i == 0) dcs_reg_write_all_chan(rDCS_MCU_MODEREG, dcs_params.modereg);
}
dcs_reg_write_all_chan(rDCS_MCU_AUTOREF_PARAMS, dcs_params.autoref_params);
dcs_reg_write_all_chan(rDCS_MCU_PDN, dcs_params.pdn);
dcs_reg_write_all_chan(rDCS_MCU_DERATE_FREQ(0), dcs_params.freq[0].derate);
// These register writes to be skipped for Maui A0/A1, but written to for B0 & later, and all other SoCs
if((dcs_cfg.chipID != 0x8000) || (dcs_cfg.chipID == 0x8000 && dcs_cfg.chipRev >= CHIP_REVISION_B0))
for(i = 1; i < DCS_FREQUENCY_SLOTS; i++)
dcs_reg_write_all_chan(rDCS_MCU_DERATE_FREQ(i), dcs_params.freq[i].derate);
for(i = 0; i < DCS_FREQUENCY_SLOTS; i++)
dcs_reg_write_all_chan(rDCS_MCU_LAT_FREQ(i), dcs_params.freq[i].lat2);
for(i = 0; i < DCS_FREQUENCY_SLOTS; i++)
dcs_reg_write_all_chan(rDCS_MCU_TAT_FREQ(i), dcs_params.freq[i].tat);
dcs_reg_write_all_chan(rDCS_MCU_RNKCFG, dcs_params.rnkcfg);
dcs_reg_write_all_chan(rDCS_MCU_MIFQMAXCTRL_FREQ(0), dcs_params.freq[0].mifqmaxctrl);
dcs_reg_write_all_chan(rDCS_MCU_MIFQMAXCTRL_FREQ(3), dcs_params.freq[3].mifqmaxctrl);
dcs_reg_write_all_chan(rDCS_MCU_PWRMNGTEN, 0);
dcs_reg_write_all_chan(rDCS_MCU_ODTSZQC, 0x00002000);
dcs_reg_write_all_chan(rDCS_MCU_AMCCTRL, 0x00000002);
dcs_reg_write_all_chan(rDCS_MCU_MCPHYUPDTPARAM, 0x15030000);
}
//================================================================================
// Step 2: AMP Initial Configuration
//================================================================================
void dcs_init_AMP_Initial_Config(void)
{
int i;
for(i = AMP_CA ; i < DCS_AMP_NUM_PHYS; i++)
dcs_reg_write_all_chan(rDCS_AMP_AMPEN(i), 0x00000001);
for(i = 0; i < DCS_FREQUENCY_SLOTS; i++)
dcs_reg_write_all_chan(rDCS_AMP_NONDQDSPD_F(i), dcs_params.freq[i].nondqdspd);
for(i = 1; i < DCS_FREQUENCY_SLOTS; i++)
dcs_reg_write_all_chan(rDCS_AMP_NONDQDS_F(i), dcs_params.freq[i].nondqds);
dcs_reg_write_all_chan(rDCS_AMP_CACKCSWKDS, dcs_params.cackcswkds);
for(i = 0; i < DCS_FREQUENCY_SLOTS; i++)
dcs_reg_write_all_chan(rDCS_AMP_VREF_F(AMP_CA, i), dcs_params.freq[i].cavref);
dcs_reg_write_all_chan(rDCS_AMP_ODTENABLE_F(0), dcs_params.freq[0].odt_enable);
dcs_reg_write_all_chan(rDCS_AMP_ODTENABLE_F(1), dcs_params.freq[1].odt_enable);
dcs_reg_write_all_chan(rDCS_AMP_ODTENABLE_F(3), dcs_params.freq[3].odt_enable);
for(i = 0; i < DCS_FREQUENCY_SLOTS; i++) {
// These register writes to be skipped for Maui A0/A1
if((dcs_cfg.chipID != 0x8000) || (dcs_cfg.chipID == 0x8000 && dcs_cfg.chipRev >= CHIP_REVISION_B0)) {
dcs_reg_write_all_chan(rDCS_AMP_DQDS_F(AMP_DQ0,i), dcs_params.freq[i].dqds);
dcs_reg_write_all_chan(rDCS_AMP_DQDS_F(AMP_DQ1,i), dcs_params.freq[i].dqds);
}
dcs_reg_write_all_chan(rDCS_AMP_DQDQSDS_F(AMP_DQ0,i), dcs_params.freq[i].dqdqsds);
dcs_reg_write_all_chan(rDCS_AMP_DQDQSDS_F(AMP_DQ1,i), dcs_params.freq[i].dqdqsds);
}
for(i = 0; i < DCS_FREQUENCY_SLOTS; i++) {
dcs_reg_write_all_chan(rDCS_AMP_VREF_F(AMP_DQ0, i), dcs_params.freq[i].dqvref);
dcs_reg_write_all_chan(rDCS_AMP_VREF_F(AMP_DQ1, i), dcs_params.freq[i].dqvref);
}
dcs_reg_write_all_chan(rDCS_AMP_DQSPDRES(AMP_DQ0), dcs_params.dqspdres);
dcs_reg_write_all_chan(rDCS_AMP_DQSPDRES(AMP_DQ1), dcs_params.dqspdres);
dcs_reg_write_all_chan(rDCS_AMP_SDLL_UPDATE_CNTL(AMP_CA), dcs_params.casdllupdatectrl);
dcs_reg_write_all_chan(rDCS_AMP_SDLL_UPDATE_CNTL(AMP_DQ0), dcs_params.dqsdllupdatectrl);
dcs_reg_write_all_chan(rDCS_AMP_SDLL_UPDATE_CNTL(AMP_DQ1), dcs_params.dqsdllupdatectrl);
dcs_reg_write_all_chan(rDCS_AMP_RDSDLLCTRL(AMP_DQ0), dcs_params.rdsdllctrl_step2);
dcs_reg_write_all_chan(rDCS_AMP_RDSDLLCTRL(AMP_DQ1), dcs_params.rdsdllctrl_step2);
dcs_reg_poll_all_chan(rDCS_AMP_RDSDLLCTRL(AMP_DQ0), dcs_params.rdsdllctrl_step2 & 0x7, 0x0);
dcs_reg_poll_all_chan(rDCS_AMP_RDSDLLCTRL(AMP_DQ1), dcs_params.rdsdllctrl_step2 & 0x7, 0x0);
dcs_reg_write_all_chan(rDCS_AMP_WRDQDQSSDLLCTRL(AMP_DQ0), dcs_params.wrdqdqssdllctrl_step2);
dcs_reg_write_all_chan(rDCS_AMP_WRDQDQSSDLLCTRL(AMP_DQ1), dcs_params.wrdqdqssdllctrl_step2);
dcs_reg_poll_all_chan(rDCS_AMP_WRDQDQSSDLLCTRL(AMP_DQ0), dcs_params.wrdqdqssdllctrl_step2 & 0x7, 0x0);
dcs_reg_poll_all_chan(rDCS_AMP_WRDQDQSSDLLCTRL(AMP_DQ1), dcs_params.wrdqdqssdllctrl_step2 & 0x7, 0x0);
dcs_reg_write_all_chan(rDCS_AMP_CAWRLVLSDLLCODE, dcs_params.cawrlvlsdllcode);
dcs_reg_poll_all_chan(rDCS_AMP_CAWRLVLSDLLCODE, dcs_params.cawrlvlsdllcode & 0x300, 0x000);
if (!izFPGA)
for(i = AMP_CA ; i < DCS_AMP_NUM_PHYS; i++)
dcs_reg_write_all_chan(rDCS_AMP_DLLLOCKTIM(i), dcs_params.dlllocktim);
if(dcs_cfg.chipID == 0x8000 && dcs_cfg.chipRev >= CHIP_REVISION_B0) {
dcs_reg_write_all_chan(rDCS_AMP_DQSPDENALWYSON(AMP_DQ0), 0x00000001);
dcs_reg_write_all_chan(rDCS_AMP_DQSPDENALWYSON(AMP_DQ1), 0x00000001);
}
if((dcs_params.supported_freqs & DCS_FREQ(1)) != 0)
dcs_reg_write_all_chan(rDCS_AMP_DFICALTIMING, dcs_params.dficaltiming);
// These register writes to be skipped for Maui A0/A1
if((dcs_cfg.chipID != 0x8000) || (dcs_cfg.chipID == 0x8000 && dcs_cfg.chipRev >= CHIP_REVISION_B0)) {
for(i = 1; i < DCS_FREQUENCY_SLOTS; i++)
dcs_reg_write_all_chan(rDCS_AMPCA_DFICALTIMING_F(i), dcs_params.freq[i].cadficaltiming);
for(i = 0; i < DCS_FREQUENCY_SLOTS; i++) {
dcs_reg_write_all_chan(rDCS_AMPDQ_DFICALTIMING_F(AMP_DQ0, i), dcs_params.freq[i].dqdficaltiming);
dcs_reg_write_all_chan(rDCS_AMPDQ_DFICALTIMING_F(AMP_DQ1, i), dcs_params.freq[i].dqdficaltiming);
}
dcs_reg_write_all_chan(rDCS_AMP_MDLLCODE_CAP_CNTL(AMP_DQ0), 0x00000002);
dcs_reg_write_all_chan(rDCS_AMP_MDLLCODE_CAP_CNTL(AMP_DQ1), 0x00000002);
}
dcs_reg_write_all_chan(rDCS_AMP_RDWRDQCALTIMING_F(0), dcs_params.rdwrdqcaltiming_f0);
dcs_reg_write_all_chan(rDCS_AMP_RDWRDQCALSEGLEN_F(0), dcs_params.rdwrdqcalseglen_f0);
dcs_reg_write_all_chan(rDCS_AMP_RDWRDQCALTIMING_F(1), dcs_params.rdwrdqcaltiming_f1);
dcs_reg_write_all_chan(rDCS_AMP_RDWRDQCALSEGLEN_F(1), dcs_params.rdwrdqcalseglen_f1);
dcs_reg_write_all_chan(rDCS_AMP_HWRDWRDQCALTIMINGCTRL(1), dcs_params.rdwrdqcaltimingctrl1);
dcs_reg_write_all_chan(rDCS_AMP_HWRDWRDQCALTIMINGCTRL(2), dcs_params.rdwrdqcaltimingctrl2);
dcs_reg_write_all_chan(rDCS_AMP_HWRDDQCALPATPRBS4I, dcs_params.rddqcalpatprbs4i);
dcs_reg_write_all_chan(rDCS_AMP_HWWRDQCALPATPRBS4I, dcs_params.wrdqcalpatprbs4i);
dcs_reg_write_all_chan(rDCS_AMP_RDDQCALWINDOW_F(0), dcs_params.freq[0].rddqcalwindow);
dcs_reg_write_all_chan(rDCS_AMP_WRDQCALWINDOW_F(0), dcs_params.freq[0].wrdqcalwindow);
dcs_reg_write_all_chan(rDCS_AMP_RDDQCALWINDOW_F(1), dcs_params.freq[1].rddqcalwindow);
dcs_reg_write_all_chan(rDCS_AMP_WRDQCALWINDOW_F(1), dcs_params.freq[1].wrdqcalwindow);
dcs_reg_write_all_chan(rDCS_AMP_MAXRDDQS_SDLL_MULFACTOR, dcs_params.maxrddqssdllmulfactor);
dcs_reg_write_all_chan(rDCS_AMP_MAXWRDQ_SDLL_MULFACTOR, 0x00a00a0f);
dcs_reg_write_all_chan(rDCS_AMP_MAXWRDQS_SDLL_MULFACTOR, dcs_params.maxwrdqssdllmulfactor);
// These register writes to be skipped for Maui A0/A1
if((dcs_cfg.chipID != 0x8000) || (dcs_cfg.chipID == 0x8000 && dcs_cfg.chipRev >= CHIP_REVISION_B0)) {
dcs_reg_write_all_chan(rDCS_AMPDQ_RDDQSMULFACTOR(AMP_DQ0), 0x20181000);
dcs_reg_write_all_chan(rDCS_AMPDQ_RDDQSMULFACTOR(AMP_DQ1), 0x20181000);
}
for(i = 0; i < DCS_FREQUENCY_SLOTS; i++) {
dcs_reg_write_all_chan(rDCS_AMP_CAOUTDLLSCL_FREQ(i), dcs_params.freq[i].caoutdllscl);
dcs_reg_write_all_chan(rDCS_AMP_DQSINDLLSCL_FREQ(AMP_DQ0, i), dcs_params.freq[i].dqsindllscl);
dcs_reg_write_all_chan(rDCS_AMP_DQSINDLLSCL_FREQ(AMP_DQ1, i), dcs_params.freq[i].dqsindllscl);
dcs_reg_write_all_chan(rDCS_AMP_RDCAPCFG_FREQ(AMP_DQ0, i), dcs_params.freq[i].rdcapcfg);
dcs_reg_write_all_chan(rDCS_AMP_RDCAPCFG_FREQ(AMP_DQ1, i), dcs_params.freq[i].rdcapcfg);
}
if (!izFPGA) {
for(i = AMP_CA ; i < DCS_AMP_NUM_PHYS; i++)
dcs_reg_write_all_chan(rDCS_AMP_DLLUPDTCTRL(i), dcs_params.dllupdtctrl1);
dcs_reg_write_all_chan(rDCS_AMP_IMPAUTOCAL, 0x00010000);
}
dcs_reg_write_all_chan(rDCS_AMP_DLLUPDTINTVL(AMP_CA), dcs_params.dllupdtintvl);
dcs_reg_write_all_chan(rDCS_AMP_DLLUPDTINTVL(AMP_DQ0), dcs_params.dllupdtintvl);
dcs_reg_write_all_chan(rDCS_AMP_DLLUPDTINTVL(AMP_DQ1), dcs_params.dllupdtintvl);
for(i = AMP_CA ; i < DCS_AMP_NUM_PHYS; i++)
dcs_reg_write_all_chan(rDCS_AMP_DLLEN(i), 0x00000100);
if(!izFPGA) {
dcs_reg_write_all_chan(rDCS_AMP_IMPCALCMD, 0x00000000);
}
// Workaround for Maui B0
if((dcs_cfg.chipID == 0x8000 && dcs_cfg.chipRev >= CHIP_REVISION_B0))
dcs_reg_write_all_chan(rDCS_AMP_BISTRXMODE, 0x0000001c);
// AMPH configuration
dcs_reg_write_all_chan(rDCS_AMPH_CB_WKPUPD, 0);
dcs_reg_write_all_chan(rDCS_AMPH_CB_DRIVESTR, dcs_params.cbdrivestr);
dcs_reg_write_all_chan(rDCS_AMPH_CB_IOCTL, dcs_params.cbioctl);
dcs_reg_write_all_chan(rDCS_AMPH_CK_WKPUPD, 0);
dcs_reg_write_all_chan(rDCS_AMPH_CK_ZDETBIASEN, 0);
dcs_reg_write_all_chan(rDCS_AMPH_CK_DRIVESTR, dcs_params.ckdrivestr);
dcs_reg_write_all_chan(rDCS_AMPH_CK_IOCTL, dcs_params.ckioctl);
dcs_reg_write_all_chan(rDCS_AMPH_B0_DRIVESTR, dcs_params.b0drivestr);
dcs_reg_write_all_chan(rDCS_AMPH_B0_IMPCTL, 0x00201c2b);
dcs_reg_write_all_chan(rDCS_AMPH_B0_WKPUPD, 0);
dcs_reg_write_all_chan(rDCS_AMPH_B0_IOCTL, dcs_params.b0ioctl);
dcs_reg_write_all_chan(rDCS_AMPH_B0_ODT, dcs_params.b0odt);
dcs_reg_write_all_chan(rDCS_AMPH_B0_ODTCTRL, dcs_params.b0odtctrl);
dcs_reg_write_all_chan(rDCS_AMPH_B1_DRIVESTR, dcs_params.b1drivestr);
dcs_reg_write_all_chan(rDCS_AMPH_B1_ODTCTRL, dcs_params.b1odtctrl);
dcs_reg_write_all_chan(rDCS_AMPH_B1_IMPCTL, 0x00201c2b);
dcs_reg_write_all_chan(rDCS_AMPH_B1_WKPUPD, 0);
dcs_reg_write_all_chan(rDCS_AMPH_B1_IOCTL, dcs_params.b1ioctl);
dcs_reg_write_all_chan(rDCS_AMPH_B1_ODT, dcs_params.b1odt);
dcs_reg_write_all_chan(rDCS_AMPH_DQS0_WKPUPD, 0x00000788);
dcs_reg_write_all_chan(rDCS_AMPH_DQS0_DRIVESTR, dcs_params.dqs0drivestr);
dcs_reg_write_all_chan(rDCS_AMPH_DQS0_IMPCTL, 0x00201c2b);
dcs_reg_write_all_chan(rDCS_AMPH_DQS0_IOCTL, dcs_params.dqs0ioctl);
dcs_reg_write_all_chan(rDCS_AMPH_DQS0_ODT, dcs_params.dqs0odt);
dcs_reg_write_all_chan(rDCS_AMPH_DQS0_ZDETBIASEN, dcs_params.dqs0zdetbiasen);
dcs_reg_write_all_chan(rDCS_AMPH_DQS0_ODTCTRL, dcs_params.dqs0odtctrl);
dcs_reg_write_all_chan(rDCS_AMPH_DQS1_WKPUPD, 0x00000788);
dcs_reg_write_all_chan(rDCS_AMPH_DQS1_DRIVESTR, dcs_params.dqs1drivestr);
dcs_reg_write_all_chan(rDCS_AMPH_DQS1_IMPCTL, 0x00201c2b);
dcs_reg_write_all_chan(rDCS_AMPH_DQS1_IOCTL, dcs_params.dqs1ioctl);
dcs_reg_write_all_chan(rDCS_AMPH_DQS1_ODT, dcs_params.dqs1odt);
dcs_reg_write_all_chan(rDCS_AMPH_DQS1_ZDETBIASEN, dcs_params.dqs1zdetbiasen);
dcs_reg_write_all_chan(rDCS_AMPH_DQS1_ODTCTRL, dcs_params.dqs1odtctrl);
dcs_reg_write_all_chan(rDCS_AMPH_DBG_REG0, 0x00000000);
dcs_reg_write_all_chan(rDCS_AMPH_ZCAL_FSM(1), dcs_params.zcalfsm1);
dcs_reg_write_all_chan(rDCS_AMPH_ZCAL_FSM(0), dcs_params.zcalfsm0);
dcs_reg_write_all_chan(rDCS_AMPH_SPARE(0), dcs_params.spare0);
for(i = AMP_CA ; i < DCS_AMP_NUM_PHYS; i++)
dcs_reg_write_all_chan(rDCS_AMP_AMPINIT(i), 0x00000001);
}
//================================================================================
// Step 3: Self-Refresh Exit
//================================================================================
void dcs_init_Self_Refresh_Exit_a(void)
{
// Wait 5 us after Impedence Calibration to avoid McPhyPending
// preventing the SRFSM from exiting SR.
dcs_spin(5, "after Imp. Cal.");
dcs_reg_write_all_chan(rDCS_MCU_AREFPARAM, dcs_params.arefparam);
for(int i = 0; i < DCS_FREQUENCY_SLOTS; i++)
dcs_reg_write_all_chan(rDCS_MCU_AUTOREF_FREQ(i), dcs_params.freq[i].autoref2);
dcs_reg_write_all_chan(rDCS_MCU_AUTOREF_PARAMS, dcs_params.autoref_params2);
dcs_reg_write_all_chan(rDCS_MCU_ODTSZQC, dcs_params.odtszqc);
dcs_reg_write_all_chan(rDCS_MCU_LONGSR, dcs_params.longsr);
dcs_reg_write_all_chan(rDCS_MCU_MCPHYUPDTPARAM, 0x15030007);
}
//========================================
// Caller Code should:
// - Change Frequency to 50MHz
//========================================
void dcs_init_Self_Refresh_Exit_b(void)
{
dcs_reg_write_all_chan(rDCS_MCU_AMCCTRL, 0x00000003);
if (!izFPGA) {
dcs_reg_write_all_chan(rDCS_AMP_IMPCALCMD, 0x00000001);
dcs_reg_poll_all_chan(rDCS_AMP_IMPCALCMD, 0x01, 0x00);
}
if (izResume)
dcs_enable_autorefresh();
dcs_spin(2200, "After Enable Auto-Refresh");
if((dcs_cfg.chipID != 0x8000) || (dcs_cfg.chipID == 0x8000 && dcs_cfg.chipRev >= CHIP_REVISION_B0)) {
dcs_reg_write_all_chan(rDCS_MCU_FREQCHNGCTL, dcs_params.freqchngctl_step3);
dcs_reg_poll_all_chan(rDCS_MCU_FREQCHNGCTL, 0x10000, 0x00000);
dcs_spin(2, "After SoC Update");
}
// Resume-Boot and Cold-Boot use different Exit commands for Self-Refresh
// Issue self-refresh exit cmd for resume boot with MPC
int n = (izColdBoot)? 0x00000000:0x00004000;
// Issue self-refresh exit cmd for resume boot with MPC
dcs_reg_write_all_chan(rDCS_MCU_MRINITCMD_0, n);
dcs_reg_write_all_chan(rDCS_MCU_MRINITCMD_0, n | 0x1);
dcs_reg_poll_all_chan(rDCS_MCU_MRINITCMD_0, 0x01, 0x00);
dcs_spin(2, NULL);
dcs_reg_write(rGLBTIMER_CHEN, (1 << dcs_cfg.num_dcs) - 1);
}
//================================================================================
// Step 4: DRAM Reset, ZQ Calibration & Configuration (cold boot only)
//================================================================================
void dcs_init_ZQ_Cal_Cfg(void)
{
// ZQ calibration START MPC cmd
dcs_mrcmd(MR_MPC, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x0, 0x4f);
// wait 1us for tZQCAL
dcs_spin(1, "tZQCAL");
// ZQ calibration LATCH MPC cmd
dcs_mrcmd(MR_MPC, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x0, 0x51);
// wait 10ns for tZQLAT
dcs_spin(1, "tZQLAT");
if (izColdBoot) {
// MR2 register (read/write latency)
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x2, 0x0);
// MR1 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x1, 0x8e);
// MR3 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x3, dcs_params.mr3cmd);
// MR22 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x16, 0x0);
// MR11 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0xb, 0x0);
// MR13 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0xd, dcs_params.mr13cmd);
// MR12 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0xc, 0x59);
// MR14 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0xe, 0x59);
// MR23 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x17, 0x80);
uint32_t patinvertmask = (DCS_REG_READ_CH(0, rDCS_AMP_HWRDDQCALPATPRBS4I) >> 16) & 0xffff;
uint32_t prbs = DCS_REG_READ_CH(0, rDCS_AMP_HWWRDQCALPATPRBS4I);
// MR15 register
dcs_mrcmd(MR_MPC, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0xf, patinvertmask & 0xff);
// MR20 register
dcs_mrcmd(MR_MPC, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x14, (patinvertmask >> 8) & 0xff);
// MR32 register
dcs_mrcmd(MR_MPC, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x20, prbs & 0xff);
// MR40 register
dcs_mrcmd(MR_MPC, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x28, (prbs >> 8) & 0xff);
}
}
//================================================================================
// Step 5a: AddrConfig Configuration
//================================================================================
void dcs_init_AddrCfg_Cfg(void)
{
dcs_reg_write(rAMCC_ADDRCFG_ADDR, dcs_params.addrcfg);
}
//========================================
// Caller Code should:
// - Use MR Cmds to Query the Device
//========================================
//================================================================================
// Step 5b: Total Mem Size Config
//================================================================================
void dcs_init_TotalSize_Cfg(uint32_t total_size_Mbytes)
{
dbgprintf(DCS_DBG_ASSESS_CONFIG, "Memory_size: %llu bytes\n",
(((uint64_t)total_size_Mbytes) * MEG * NUM_AMCCS));
// (Units of 128 MBs in the register)
dcs_reg_write(rAMCC_DRAMACCCTRL_ADDR, ((total_size_Mbytes / NUM_AMCCS) / DCS_NUM_MEG_IN_DRAM_BLK) - 1);
dcs_reg_write(rAMCC_MCCCHNLDEC_ADDR, dcs_params.chnldec);
dbgprintf(DCS_DBG_ASSESS_CONFIG, "rAMCC_DRAMACCCTRL: 0x%08x\n", rAMCC_DRAMACCCTRL);
}
//================================================================================
// Step 6: Switch from boot-clock speed to normal operation speed
//================================================================================
void dcs_init_Reenable_AMC_Scheduler(void)
{
// Wait 5 us before freq change to make sure all refreshes have been flushed
dcs_spin(5, "After Refresh");
// Enable (again) the AMC Scheduler
dcs_reg_write_all_chan(rDCS_MCU_AMCCTRL, 0x00000003);
}
//================================================================================
// Step 7: Setup registers for CA calibration for bucket 1
//================================================================================
void dcs_init_CA_Cal_Setup_Freq1(void)
{
// MR13 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0xd, dcs_params.mr13cmd_step7);
if (izColdBoot) {
if (izFPGA) {
// MR11 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0xb, 0x00);
} else {
// MR2 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x2, 0x52);
// MR1 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x1, 0xae);
// MR3 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x3, dcs_params.mr3cmd_step7);
// MR22 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x16, dcs_params.mr22cmd);
// MR11 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0xb, dcs_params.mr11cmd);
// MR12 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0xc, 0x11);
// MR14 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0xe, 0x11);
}
dcs_reg_write_all_chan(rDCS_AMP_CAWRLVLSDLLCODE, 0x00000200);
dcs_reg_poll_all_chan(rDCS_AMP_CAWRLVLSDLLCODE, 0x0200, 0x0000);
}
}
//================================================================================
// Step 8: AMP Dynamic CA Vref Timing Calibration at Vmin 800MHz
//================================================================================
void dcs_init_CA_Cal_Freq1(void)
{
// Nothing to be done at this step for cold boot
}
//================================================================================
// Step 9: Setup registers for DQ calibration for bucket 1
//================================================================================
void dcs_init_DQ_Cal_Setup_Freq1_a(void)
{
int i;
if (izColdBoot) {
// MR13 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0xd, dcs_params.mr13cmd_step9);
}
dcs_spin(1, NULL);
if(izResume) {
dcs_reg_write_all_chan(rDCS_MCU_PWRMNGTEN, 0x00000002);
dcs_reg_write_all_chan(rDCS_MCU_FREQCHNGCTL, 0x01008888);
for(i = AMP_DQ0 ; i < DCS_AMP_NUM_PHYS; i++)
dcs_reg_write_all_chan(rDCS_AMP_WRDQDQSSDLLCTRL(i), 0xFF00000C);
for(i = AMP_CA ; i < DCS_AMP_NUM_PHYS; i++)
dcs_reg_write_all_chan(rDCS_AMP_SDLL_UPDATE_DEFER_EN(i), 0x00000000);
for(i = AMP_DQ0; i < DCS_AMP_NUM_PHYS; i++)
dcs_reg_write_all_chan(rDCS_AMP_MDLLOVRRD(i), 0x00000000);
}
}
// Caller code should change frequency to bucket 1
void dcs_init_DQ_Cal_Setup_Freq1_b(void)
{
if (izColdBoot) {
if((dcs_cfg.chipID != 0x8000) || (dcs_cfg.chipID == 0x8000 && dcs_cfg.chipRev >= CHIP_REVISION_B0)) {
dcs_reg_write_all_chan(rDCS_MCU_FREQCHNGCTL, dcs_params.freqchngctl_step9);
dcs_reg_poll_all_chan(rDCS_MCU_FREQCHNGCTL, 0x10000, 0x00000);
// Wait 2us for the soc update to finish
dcs_spin(2, NULL);
}
}
}
//================================================================================
// Step 10: PHY write DQ calibration
//================================================================================
void dcs_init_wrdq_skew(void)
{
dcs_reg_write_all_chan(rDCS_AMP_DQSDQ_SKEWCTL(AMP_DQ0), 0x06000000);
dcs_reg_write_all_chan(rDCS_AMP_DQSDQ_SKEWCTL(AMP_DQ1), 0x06000000);
}
void dcs_init_post_wrlvl(void)
{
if(dcs_cfg.chipID == 0x8000 && dcs_cfg.chipRev >= CHIP_REVISION_B0) {
dcs_reg_write_all_chan(rDCS_AMP_DQFLTCTRL(AMP_DQ0), 0x00000010);
dcs_reg_write_all_chan(rDCS_AMP_DQFLTCTRL(AMP_DQ1), 0x00000010);
}
dcs_reg_write_all_chan(rDCS_AMPH_DQS0_WKPUPD, dcs_params.dqs0wkpupd);
dcs_reg_write_all_chan(rDCS_AMPH_DQS1_WKPUPD, dcs_params.dqs1wkpupd);
}
//================================================================================
// Step 11: Setup registers for CA calibration for bucket 0
//================================================================================
void dcs_init_CA_Cal_Setup_Freq0(void)
{
if (izColdBoot) {
if(dcs_cfg.chipID == 0x8000 && dcs_cfg.chipRev >= CHIP_REVISION_B0) {
dcs_reg_write_all_chan(rDCS_AMP_DQFLTCTRL(AMP_DQ0), 0x00000000);
dcs_reg_write_all_chan(rDCS_AMP_DQFLTCTRL(AMP_DQ1), 0x00000000);
}
dcs_reg_write_all_chan(rDCS_AMPH_DQS0_WKPUPD, 0x00000788);
dcs_reg_write_all_chan(rDCS_AMPH_DQS1_WKPUPD, 0x00000788);
// MR13 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x0d, dcs_params.mr13cmd_step11);
if (!izFPGA) {
// MR2 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x02, dcs_params.mr2cmd_step11);
// MR1 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x01, dcs_params.mr1cmd_step11);
// MR3 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x03, dcs_params.mr3cmd_step11);
}
// MR22 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x16, dcs_params.mr22cmd_step11);
// MR11 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x0b, (izFPGA) ? 0x00 : dcs_params.mr11cmd_step11);
// MR12 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x0c, dcs_params.mr12cmd_step11);
// MR14 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x0e, dcs_params.mr14cmd_step11);
if((dcs_params.supported_freqs & DCS_FREQ(1)) == 0) {
dcs_reg_write_all_chan(rDCS_AMP_CAWRLVLSDLLCODE, 0x00000200);
dcs_reg_poll_all_chan(rDCS_AMP_CAWRLVLSDLLCODE, 0x200, 0x000);
}
}
}
//================================================================================
// Step 12: AMP Dynamic CA Timing Calibration
//================================================================================
//================================================================================
// Step 13: Setup registers for DQ calibration for bucket 0
//================================================================================
void dcs_init_DQ_Cal_Setup_Freq0_a(void)
{
if (izColdBoot) {
// MR13 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x0d, dcs_params.mr13cmd_step13);
// Wait 1 us
dcs_spin(1, NULL);
}
}
void dcs_init_DQ_Cal_Setup_Freq0_b(void)
{
if (izColdBoot) {
if((dcs_cfg.chipID != 0x8000) || (dcs_cfg.chipID == 0x8000 && dcs_cfg.chipRev >= CHIP_REVISION_B0)) {
dcs_reg_write_all_chan(rDCS_MCU_FREQCHNGCTL, 0x00010000);
dcs_reg_poll_all_chan(rDCS_MCU_FREQCHNGCTL, 0x10000, 0x00000);
// Wait 2us for the soc update to finish
dcs_spin(2, NULL);
}
}
}
//================================================================================
// Step 14: AMP Dynamic DQ Calibration
//================================================================================
//================================================================================
// Step 15: Setup Registers for Boot
//================================================================================
void dcs_init_Reg_for_Boot(void)
{
if (dcs_cfg.chipRev > CHIP_REVISION_A0)
dcs_reg_write_all_chan(rDCS_AMPH_SPARE(0), 0x0000040e);
#ifndef DCS_RUN_AT_50MHZ
if (izColdBoot) {
// MR13 register
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x0d, dcs_params.mr13cmd_step15);
}
#endif
if(izFPGA && !(dcs_params.supported_freqs & DCS_FREQ(1)))
dcs_mrcmd(MR_WRITE, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x0d, 0x50);
// Wait 1 us
dcs_spin(1, NULL);
if (izColdBoot) {
dcs_reg_write_all_chan(rDCS_MCU_FREQCHNGCTL, dcs_params.freqchngctl_step15);
dcs_reg_write_all_chan(rDCS_AMP_WRDQDQSSDLLCTRL(AMP_DQ0), 0xff000008);
dcs_reg_write_all_chan(rDCS_AMP_WRDQDQSSDLLCTRL(AMP_DQ1), 0xff000008);
#if !DCS_DO_CALIBRATION
// skip these for all silicon targets, where calibration is performed, also skip for any Maui A1 target
if((dcs_cfg.chipID != 0x8000) || (dcs_cfg.chipID == 0x8000 && dcs_cfg.chipRev >= CHIP_REVISION_B0)) {
dcs_reg_write_all_chan(rDCS_AMP_RDSDLLCTRL(AMP_DQ0), dcs_params.rdsdllctrl_step15);
dcs_reg_write_all_chan(rDCS_AMP_RDSDLLCTRL(AMP_DQ1), dcs_params.rdsdllctrl_step15);
dcs_reg_poll_all_chan(rDCS_AMP_RDSDLLCTRL(AMP_DQ0), dcs_params.rdsdllctrl_step15 & 0x7, 0x0);
dcs_reg_poll_all_chan(rDCS_AMP_RDSDLLCTRL(AMP_DQ1), dcs_params.rdsdllctrl_step15 & 0x7, 0x0);
}
#endif
}
dcs_reg_write_all_chan(rDCS_AMP_HWRDWRDQCALFULLSCANEN, 0x00000000);
dcs_reg_write_all_chan(rDCS_AMP_HWRDWRDQCALFULLSCANEN, 0x00000003);
}
//================================================================================
// Step 16: Enable Other Features
//================================================================================
void dcs_init_MoreFeatures(void)
{
dcs_reg_write_all_chan(rDCS_MCU_AREFPARAM, dcs_params.arefparam);
dcs_reg_write_all_chan(rDCS_MCU_ODTSZQC, dcs_params.odtszqc2);
dcs_reg_write_all_chan(rDCS_MCU_QBREN, dcs_params.qbren_step16);
if (izColdBoot)
dcs_enable_autorefresh();
dcs_reg_write_all_chan(rDCS_AMPH_B0_DYN_ISEL_ASRTIME, dcs_params.b0dyniselasrtime);
dcs_reg_write_all_chan(rDCS_AMPH_B0_DYN_ISEL, dcs_params.b0dynisel);
dcs_reg_write_all_chan(rDCS_AMPH_B1_DYN_ISEL, dcs_params.b1dynisel);
dcs_reg_write_all_chan(rDCS_AMPH_DQS0_DCD_IOCTL, 0x00030000);
dcs_reg_write_all_chan(rDCS_AMPH_DQS1_DCD_IOCTL, 0x00030000);
}
//================================================================================
// Step 17: Enable Fast Critical Word Forwarding Feature
//================================================================================
void dcs_init_Fast_Critical_Word_Forwarding(void)
{
dcs_reg_write_all_chan(rDCS_MCU_QBRPARAM, dcs_params.qbrparam);
dcs_reg_write_all_chan(rDCS_MCU_QBREN, dcs_params.qbren);
dcs_reg_poll(rAMCC_MCCPWRONWAYCNTSTATUS_ADDR, 0x7fff7fff, 0x42104210);
dcs_reg_write(rAMCC_MCC0QPROPCTRL_ADDR, 0x300011a2);
dcs_reg_write(rAMCC_MCC1QPROPCTRL_ADDR, 0x300011a2);
dcs_reg_write(rAMCC_MCCGEN_ADDR, dcs_params.mccgen);
}
//================================================================================
// Step 18: Enable Power- and Clock-Gating Features; Config MCC and Global Timers
//================================================================================
void dcs_init_Gating_Global_Timers(void)
{
const struct dcs_memory_device_info *dev_info = dcs_get_memory_device_info();
dcs_reg_write_all_chan(rDCS_AMP_AMPCLK(AMP_CA), dcs_params.caampclk);
dcs_reg_write_all_chan(rDCS_AMP_AMPCLK(AMP_DQ0), dcs_params.dqampclk);
dcs_reg_write_all_chan(rDCS_AMP_AMPCLK(AMP_DQ1), dcs_params.dqampclk);
dcs_reg_write_all_chan(rDCS_MCU_PWRMNGTEN, dcs_params.pwrmngten);
if(!izFPGA) {
dcs_reg_write_all_chan(rDCS_MCU_PWRMNGTPARAM_FREQ(0), 0x01800000);
dcs_reg_write_all_chan(rDCS_MCU_PSQWQCTL1, 0x01640120);
}
// Global Timer Setup
if(dcs_cfg.chipID == 0x8000 && dcs_cfg.chipRev < CHIP_REVISION_B0) {
dcs_reg_write(rGLBTIMER_PMGRWAKEUPCFG, 0x0000ff);
dcs_reg_write(rGLBTIMER_MDLLTIMER, 0x000bb8); // 3000
dcs_reg_write(rGLBTIMER_MDLLVOLTRAMPTIMER, 0x00004b); // 75
dcs_reg_write(rGLBTIMER_CTRLUPDMASKTIMER, 0x00000f); // 15
dcs_reg_write(rGLBTIMER_RDCALTIMER, 0x2dc6c0); // 3000000
dcs_reg_write(rGLBTIMER_WRCALTIMER, 0x2dc6c0); // 3000000
dcs_reg_write(rGLBTIMER_ZQCTIMER, 0x3d0900); // 4000000
dcs_reg_write(rGLBTIMER_PERCAL_FREQCHNGTIMER, 0x000001); // 300000
dcs_reg_write(rGLBTIMER_VOLTRAMPTIMER, 0x000001); // 300000
dcs_reg_write(rGLBTIMER_IMPCALTIMER, 0x002ee0); // 12000
} else {
dcs_reg_write(rGLBTIMER_PMGRWAKEUPCFG, 0x0000ff);
dcs_reg_write(rGLBTIMER_PREFREQ2ALLBANKDLY(0), 0x01500150);
dcs_reg_write(rGLBTIMER_PREFREQ2ALLBANKDLY(1), 0x01500150);
dcs_reg_write(rGLBTIMER_PREFREQCHNG2FREQCHNGDLY(0), 0x02a002a0);
dcs_reg_write(rGLBTIMER_PREFREQCHNG2FREQCHNGDLY(1), 0x02a002a0);
dcs_reg_write(rGLBTIMER_CAL2PREFREQCHNGDLY(0), 0x00900090);
dcs_reg_write(rGLBTIMER_CAL2PREFREQCHNGDLY(1), 0x00900090);
dcs_reg_write(rGLBTIMER_FREQCHNG2PSTCALDLY(0), 0x01200120);
dcs_reg_write(rGLBTIMER_FREQCHNG2PSTCALDLY(1), 0x01200120);
dcs_reg_write(rGLBTIMER_MDLLTIMER, 0x000bb8); // 3000
dcs_reg_write(rGLBTIMER_MDLLVOLTRAMPTIMER, 0x00004b); // 75
dcs_reg_write(rGLBTIMER_CTRLUPDMASKTIMER, 0x00000f); // 15
// skip IDTTIMER setup per spec
//dcs_reg_write(rGLBTIMER_IDTTIMER, 0x007530); // 30000
dcs_reg_write(rGLBTIMER_RDCALTIMER, 0x2dc6c0); // 3000000
dcs_reg_write(rGLBTIMER_WRCALTIMER, 0x2dc6c0); // 3000000
// <rdar://problem/23355941> Maui/Malta: Samsung DRAM workaround: disable hw zqcal
if(! ((dev_info->vendor_id == JEDEC_LPDDR4_MANUF_ID_SAMSUNG) && (dev_info->rev_id == 5) && (dev_info->rev_id2 <= 1)) )
dcs_reg_write(rGLBTIMER_ZQCTIMER, 0x3d0900); // 4000000
dcs_reg_write(rGLBTIMER_PERCAL_FREQCHNGTIMER, 0x0493e0); //
dcs_reg_write(rGLBTIMER_VOLTRAMPTIMER, 0x0493e0); //
dcs_reg_write(rGLBTIMER_IMPCALTIMER, 0x002ee0); // 12000
dcs_reg_write(rGLBTIMER_VOLTRAMP2ALLBANKDLY(0), 0x00d800d8);
dcs_reg_write(rGLBTIMER_VOLTRAMP2ALLBANKDLY(1), 0x00d800d8);
dcs_reg_write(rGLBTIMER_ALLBANK2PMGRACKDLY(0), 0x00900090);
dcs_reg_write(rGLBTIMER_ALLBANK2PMGRACKDLY(1), 0x00900090);
}
// Dynamic Clk & Power Gating
dcs_reg_write_all_chan(rDCS_MCU_AMCCLKPWRGATE, 0x050a0000);
}
//================================================================================
// Step 19: ODTS read & set interval for periodic MR4 on-die Temp sensor reading
//================================================================================
void dcs_init_ODTS(void)
{
uint8_t temp[16*8]; // Far more Channels/Ranks than we are likely ever to have/need
// INSTEAD OF: uint8_t temp[dcs_cfg.num_dcs * dcs_cfg.num_rank];
// MR4 read to bring memory out of self-refresh
dcs_mrcmd(MR_READ, dcs_cfg.num_dcs, dcs_cfg.num_rank, 0x4, (uintptr_t)temp);
dcs_reg_write_all_chan(rDCS_MCU_ODTSZQC, dcs_params.odtszqc3);
}
//================================================================================
+26
View File
@@ -0,0 +1,26 @@
# Copyright (C) 2013 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.
#
LOCAL_DIR := $(GET_LOCAL_DIR)
OPTIONS += \
WITH_HW_DCS=1
ALL_OBJS += \
$(LOCAL_DIR)/dcs.o
ifeq ($(SUB_PLATFORM),s8000)
ALL_OBJS += $(LOCAL_DIR)/dcs_init_lib_s8000.o
else ifeq ($(SUB_PLATFORM),s8001)
ALL_OBJS += $(LOCAL_DIR)/dcs_init_lib_s8001.o
else ifeq ($(SUB_PLATFORM),s8003)
ALL_OBJS += $(LOCAL_DIR)/dcs_init_lib_s8003.o
else
$(error "Unrecognized SUB_PLATFORM \"$(SUB_PLATFORM)\"")
endif