void ddrphy_init()

in arch/x86/cpu/quark/smc.c [252:1145]


void ddrphy_init(struct mrc_params *mrc_params)
{
	uint32_t temp;
	uint8_t ch;	/* channel counter */
	uint8_t rk;	/* rank counter */
	uint8_t bl_grp;	/*  byte lane group counter (2 BLs per module) */
	uint8_t bl_divisor = 1;	/* byte lane divisor */
	/* For DDR3 --> 0 == 800, 1 == 1066, 2 == 1333 */
	uint8_t speed = mrc_params->ddr_speed & 3;
	uint8_t cas;
	uint8_t cwl;

	ENTERFN();

	cas = mrc_params->params.cl;
	cwl = 5 + mrc_params->ddr_speed;

	/* ddrphy_init starts */
	mrc_post_code(0x03, 0x00);

	/*
	 * HSD#231531
	 * Make sure IOBUFACT is deasserted before initializing the DDR PHY
	 *
	 * HSD#234845
	 * Make sure WRPTRENABLE is deasserted before initializing the DDR PHY
	 */
	for (ch = 0; ch < NUM_CHANNELS; ch++) {
		if (mrc_params->channel_enables & (1 << ch)) {
			/* Deassert DDRPHY Initialization Complete */
			mrc_alt_write_mask(DDRPHY,
				CMDPMCONFIG0 + ch * DDRIOCCC_CH_OFFSET,
				~(1 << 20), 1 << 20);	/* SPID_INIT_COMPLETE=0 */
			/* Deassert IOBUFACT */
			mrc_alt_write_mask(DDRPHY,
				CMDCFGREG0 + ch * DDRIOCCC_CH_OFFSET,
				~(1 << 2), 1 << 2);	/* IOBUFACTRST_N=0 */
			/* Disable WRPTR */
			mrc_alt_write_mask(DDRPHY,
				CMDPTRREG + ch * DDRIOCCC_CH_OFFSET,
				~(1 << 0), 1 << 0);	/* WRPTRENABLE=0 */
		}
	}

	/* Put PHY in reset */
	mrc_alt_write_mask(DDRPHY, MASTERRSTN, 0, 1);

	/* Initialize DQ01, DQ23, CMD, CLK-CTL, COMP modules */

	/* STEP0 */
	mrc_post_code(0x03, 0x10);
	for (ch = 0; ch < NUM_CHANNELS; ch++) {
		if (mrc_params->channel_enables & (1 << ch)) {
			/* DQ01-DQ23 */
			for (bl_grp = 0;
			     bl_grp < (NUM_BYTE_LANES / bl_divisor) / 2;
			     bl_grp++) {
				/* Analog MUX select - IO2xCLKSEL */
				mrc_alt_write_mask(DDRPHY,
					DQOBSCKEBBCTL +
					bl_grp * DDRIODQ_BL_OFFSET +
					ch * DDRIODQ_CH_OFFSET,
					bl_grp ? 0 : (1 << 22), 1 << 22);

				/* ODT Strength */
				switch (mrc_params->rd_odt_value) {
				case 1:
					temp = 0x3;
					break;	/* 60 ohm */
				case 2:
					temp = 0x3;
					break;	/* 120 ohm */
				case 3:
					temp = 0x3;
					break;	/* 180 ohm */
				default:
					temp = 0x3;
					break;	/* 120 ohm */
				}

				/* ODT strength */
				mrc_alt_write_mask(DDRPHY,
					B0RXIOBUFCTL +
					bl_grp * DDRIODQ_BL_OFFSET +
					ch * DDRIODQ_CH_OFFSET,
					temp << 5, 0x60);
				/* ODT strength */
				mrc_alt_write_mask(DDRPHY,
					B1RXIOBUFCTL +
					bl_grp * DDRIODQ_BL_OFFSET +
					ch * DDRIODQ_CH_OFFSET,
					temp << 5, 0x60);

				/* Dynamic ODT/DIFFAMP */
				temp = (cas << 24) | (cas << 16) |
					(cas << 8) | (cas << 0);
				switch (speed) {
				case 0:
					temp -= 0x01010101;
					break;	/* 800 */
				case 1:
					temp -= 0x02020202;
					break;	/* 1066 */
				case 2:
					temp -= 0x03030303;
					break;	/* 1333 */
				case 3:
					temp -= 0x04040404;
					break;	/* 1600 */
				}

				/* Launch Time: ODT, DIFFAMP, ODT, DIFFAMP */
				mrc_alt_write_mask(DDRPHY,
					B01LATCTL1 +
					bl_grp * DDRIODQ_BL_OFFSET +
					ch * DDRIODQ_CH_OFFSET,
					temp, 0x1f1f1f1f);
				switch (speed) {
				/* HSD#234715 */
				case 0:
					temp = (0x06 << 16) | (0x07 << 8);
					break;	/* 800 */
				case 1:
					temp = (0x07 << 16) | (0x08 << 8);
					break;	/* 1066 */
				case 2:
					temp = (0x09 << 16) | (0x0a << 8);
					break;	/* 1333 */
				case 3:
					temp = (0x0a << 16) | (0x0b << 8);
					break;	/* 1600 */
				}

				/* On Duration: ODT, DIFFAMP */
				mrc_alt_write_mask(DDRPHY,
					B0ONDURCTL +
					bl_grp * DDRIODQ_BL_OFFSET +
					ch * DDRIODQ_CH_OFFSET,
					temp, 0x003f3f00);
				/* On Duration: ODT, DIFFAMP */
				mrc_alt_write_mask(DDRPHY,
					B1ONDURCTL +
					bl_grp * DDRIODQ_BL_OFFSET +
					ch * DDRIODQ_CH_OFFSET,
					temp, 0x003f3f00);

				switch (mrc_params->rd_odt_value) {
				case 0:
					/* override DIFFAMP=on, ODT=off */
					temp = (0x3f << 16) | (0x3f << 10);
					break;
				default:
					/* override DIFFAMP=on, ODT=on */
					temp = (0x3f << 16) | (0x2a << 10);
					break;
				}

				/* Override: DIFFAMP, ODT */
				mrc_alt_write_mask(DDRPHY,
					B0OVRCTL +
					bl_grp * DDRIODQ_BL_OFFSET +
					ch * DDRIODQ_CH_OFFSET,
					temp, 0x003ffc00);
				/* Override: DIFFAMP, ODT */
				mrc_alt_write_mask(DDRPHY,
					B1OVRCTL +
					bl_grp * DDRIODQ_BL_OFFSET +
					ch * DDRIODQ_CH_OFFSET,
					temp, 0x003ffc00);

				/* DLL Setup */

				/* 1xCLK Domain Timings: tEDP,RCVEN,WDQS (PO) */
				mrc_alt_write_mask(DDRPHY,
					B0LATCTL0 +
					bl_grp * DDRIODQ_BL_OFFSET +
					ch * DDRIODQ_CH_OFFSET,
					((cas + 7) << 16) | ((cas - 4) << 8) |
					((cwl - 2) << 0), 0x003f1f1f);
				mrc_alt_write_mask(DDRPHY,
					B1LATCTL0 +
					bl_grp * DDRIODQ_BL_OFFSET +
					ch * DDRIODQ_CH_OFFSET,
					((cas + 7) << 16) | ((cas - 4) << 8) |
					((cwl - 2) << 0), 0x003f1f1f);

				/* RCVEN Bypass (PO) */
				mrc_alt_write_mask(DDRPHY,
					B0RXIOBUFCTL +
					bl_grp * DDRIODQ_BL_OFFSET +
					ch * DDRIODQ_CH_OFFSET,
					0, 0x81);
				mrc_alt_write_mask(DDRPHY,
					B1RXIOBUFCTL +
					bl_grp * DDRIODQ_BL_OFFSET +
					ch * DDRIODQ_CH_OFFSET,
					0, 0x81);

				/* TX */
				mrc_alt_write_mask(DDRPHY,
					DQCTL +
					bl_grp * DDRIODQ_BL_OFFSET +
					ch * DDRIODQ_CH_OFFSET,
					1 << 16, 1 << 16);
				mrc_alt_write_mask(DDRPHY,
					B01PTRCTL1 +
					bl_grp * DDRIODQ_BL_OFFSET +
					ch * DDRIODQ_CH_OFFSET,
					1 << 8, 1 << 8);

				/* RX (PO) */
				/* Internal Vref Code, Enable#, Ext_or_Int (1=Ext) */
				mrc_alt_write_mask(DDRPHY,
					B0VREFCTL +
					bl_grp * DDRIODQ_BL_OFFSET +
					ch * DDRIODQ_CH_OFFSET,
					(0x03 << 2) | (0x0 << 1) | (0x0 << 0),
					0xff);
				/* Internal Vref Code, Enable#, Ext_or_Int (1=Ext) */
				mrc_alt_write_mask(DDRPHY,
					B1VREFCTL +
					bl_grp * DDRIODQ_BL_OFFSET +
					ch * DDRIODQ_CH_OFFSET,
					(0x03 << 2) | (0x0 << 1) | (0x0 << 0),
					0xff);
				/* Per-Bit De-Skew Enable */
				mrc_alt_write_mask(DDRPHY,
					B0RXIOBUFCTL +
					bl_grp * DDRIODQ_BL_OFFSET +
					ch * DDRIODQ_CH_OFFSET,
					0, 0x10);
				/* Per-Bit De-Skew Enable */
				mrc_alt_write_mask(DDRPHY,
					B1RXIOBUFCTL +
					bl_grp * DDRIODQ_BL_OFFSET +
					ch * DDRIODQ_CH_OFFSET,
					0, 0x10);
			}

			/* CLKEBB */
			mrc_alt_write_mask(DDRPHY,
				CMDOBSCKEBBCTL + ch * DDRIOCCC_CH_OFFSET,
				0, 1 << 23);

			/* Enable tristate control of cmd/address bus */
			mrc_alt_write_mask(DDRPHY,
				CMDCFGREG0 + ch * DDRIOCCC_CH_OFFSET,
				0, 0x03);

			/* ODT RCOMP */
			mrc_alt_write_mask(DDRPHY,
				CMDRCOMPODT + ch * DDRIOCCC_CH_OFFSET,
				(0x03 << 5) | (0x03 << 0), 0x3ff);

			/* CMDPM* registers must be programmed in this order */

			/* Turn On Delays: SFR (regulator), MPLL */
			mrc_alt_write_mask(DDRPHY,
				CMDPMDLYREG4 + ch * DDRIOCCC_CH_OFFSET,
				0xffffffff, 0xffffffff);
			/*
			 * Delays: ASSERT_IOBUFACT_to_ALLON0_for_PM_MSG_3,
			 * VREG (MDLL) Turn On, ALLON0_to_DEASSERT_IOBUFACT
			 * for_PM_MSG_gt0, MDLL Turn On
			 */
			mrc_alt_write_mask(DDRPHY,
				CMDPMDLYREG3 + ch * DDRIOCCC_CH_OFFSET,
				0xfffff616, 0xffffffff);
			/* MPLL Divider Reset Delays */
			mrc_alt_write_mask(DDRPHY,
				CMDPMDLYREG2 + ch * DDRIOCCC_CH_OFFSET,
				0xffffffff, 0xffffffff);
			/* Turn Off Delays: VREG, Staggered MDLL, MDLL, PI */
			mrc_alt_write_mask(DDRPHY,
				CMDPMDLYREG1 + ch * DDRIOCCC_CH_OFFSET,
				0xffffffff, 0xffffffff);
			/* Turn On Delays: MPLL, Staggered MDLL, PI, IOBUFACT */
			mrc_alt_write_mask(DDRPHY,
				CMDPMDLYREG0 + ch * DDRIOCCC_CH_OFFSET,
				0xffffffff, 0xffffffff);
			/* Allow PUnit signals */
			mrc_alt_write_mask(DDRPHY,
				CMDPMCONFIG0 + ch * DDRIOCCC_CH_OFFSET,
				(0x6 << 8) | (0x1 << 6) | (0x4 << 0),
				0xffe00f4f);
			/* DLL_VREG Bias Trim, VREF Tuning for DLL_VREG */
			mrc_alt_write_mask(DDRPHY,
				CMDMDLLCTL + ch * DDRIOCCC_CH_OFFSET,
				(0x3 << 4) | (0x7 << 0), 0x7f);

			/* CLK-CTL */
			mrc_alt_write_mask(DDRPHY,
				CCOBSCKEBBCTL + ch * DDRIOCCC_CH_OFFSET,
				0, 1 << 24);	/* CLKEBB */
			/* Buffer Enable: CS,CKE,ODT,CLK */
			mrc_alt_write_mask(DDRPHY,
				CCCFGREG0 + ch * DDRIOCCC_CH_OFFSET,
				0x1f, 0x000ffff1);
			/* ODT RCOMP */
			mrc_alt_write_mask(DDRPHY,
				CCRCOMPODT + ch * DDRIOCCC_CH_OFFSET,
				(0x03 << 8) | (0x03 << 0), 0x00001f1f);
			/* DLL_VREG Bias Trim, VREF Tuning for DLL_VREG */
			mrc_alt_write_mask(DDRPHY,
				CCMDLLCTL + ch * DDRIOCCC_CH_OFFSET,
				(0x3 << 4) | (0x7 << 0), 0x7f);

			/*
			 * COMP (RON channel specific)
			 * - DQ/DQS/DM RON: 32 Ohm
			 * - CTRL/CMD RON: 27 Ohm
			 * - CLK RON: 26 Ohm
			 */
			/* RCOMP Vref PU/PD */
			mrc_alt_write_mask(DDRPHY,
				DQVREFCH0 +  ch * DDRCOMP_CH_OFFSET,
				(0x08 << 24) | (0x03 << 16), 0x3f3f0000);
			/* RCOMP Vref PU/PD */
			mrc_alt_write_mask(DDRPHY,
				CMDVREFCH0 + ch * DDRCOMP_CH_OFFSET,
				(0x0C << 24) | (0x03 << 16), 0x3f3f0000);
			/* RCOMP Vref PU/PD */
			mrc_alt_write_mask(DDRPHY,
				CLKVREFCH0 + ch * DDRCOMP_CH_OFFSET,
				(0x0F << 24) | (0x03 << 16), 0x3f3f0000);
			/* RCOMP Vref PU/PD */
			mrc_alt_write_mask(DDRPHY,
				DQSVREFCH0 + ch * DDRCOMP_CH_OFFSET,
				(0x08 << 24) | (0x03 << 16), 0x3f3f0000);
			/* RCOMP Vref PU/PD */
			mrc_alt_write_mask(DDRPHY,
				CTLVREFCH0 + ch * DDRCOMP_CH_OFFSET,
				(0x0C << 24) | (0x03 << 16), 0x3f3f0000);

			/* DQS Swapped Input Enable */
			mrc_alt_write_mask(DDRPHY,
				COMPEN1CH0 + ch * DDRCOMP_CH_OFFSET,
				(1 << 19) | (1 << 17), 0xc00ac000);

			/* ODT VREF = 1.5 x 274/360+274 = 0.65V (code of ~50) */
			/* ODT Vref PU/PD */
			mrc_alt_write_mask(DDRPHY,
				DQVREFCH0 + ch * DDRCOMP_CH_OFFSET,
				(0x32 << 8) | (0x03 << 0), 0x00003f3f);
			/* ODT Vref PU/PD */
			mrc_alt_write_mask(DDRPHY,
				DQSVREFCH0 + ch * DDRCOMP_CH_OFFSET,
				(0x32 << 8) | (0x03 << 0), 0x00003f3f);
			/* ODT Vref PU/PD */
			mrc_alt_write_mask(DDRPHY,
				CLKVREFCH0 + ch * DDRCOMP_CH_OFFSET,
				(0x0E << 8) | (0x05 << 0), 0x00003f3f);

			/*
			 * Slew rate settings are frequency specific,
			 * numbers below are for 800Mhz (speed == 0)
			 * - DQ/DQS/DM/CLK SR: 4V/ns,
			 * - CTRL/CMD SR: 1.5V/ns
			 */
			temp = (0x0e << 16) | (0x0e << 12) | (0x08 << 8) |
				(0x0b << 4) | (0x0b << 0);
			/* DCOMP Delay Select: CTL,CMD,CLK,DQS,DQ */
			mrc_alt_write_mask(DDRPHY,
				DLYSELCH0 + ch * DDRCOMP_CH_OFFSET,
				temp, 0x000fffff);
			/* TCO Vref CLK,DQS,DQ */
			mrc_alt_write_mask(DDRPHY,
				TCOVREFCH0 + ch * DDRCOMP_CH_OFFSET,
				(0x05 << 16) | (0x05 << 8) | (0x05 << 0),
				0x003f3f3f);
			/* ODTCOMP CMD/CTL PU/PD */
			mrc_alt_write_mask(DDRPHY,
				CCBUFODTCH0 + ch * DDRCOMP_CH_OFFSET,
				(0x03 << 8) | (0x03 << 0),
				0x00001f1f);
			/* COMP */
			mrc_alt_write_mask(DDRPHY,
				COMPEN0CH0 + ch * DDRCOMP_CH_OFFSET,
				0, 0xc0000100);

#ifdef BACKUP_COMPS
			/* DQ COMP Overrides */
			/* RCOMP PU */
			mrc_alt_write_mask(DDRPHY,
				DQDRVPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
				(1 << 31) | (0x0a << 16),
				0x801f0000);
			/* RCOMP PD */
			mrc_alt_write_mask(DDRPHY,
				DQDRVPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
				(1 << 31) | (0x0a << 16),
				0x801f0000);
			/* DCOMP PU */
			mrc_alt_write_mask(DDRPHY,
				DQDLYPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
				(1 << 31) | (0x10 << 16),
				0x801f0000);
			/* DCOMP PD */
			mrc_alt_write_mask(DDRPHY,
				DQDLYPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
				(1 << 31) | (0x10 << 16),
				0x801f0000);
			/* ODTCOMP PU */
			mrc_alt_write_mask(DDRPHY,
				DQODTPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
				(1 << 31) | (0x0b << 16),
				0x801f0000);
			/* ODTCOMP PD */
			mrc_alt_write_mask(DDRPHY,
				DQODTPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
				(1 << 31) | (0x0b << 16),
				0x801f0000);
			/* TCOCOMP PU */
			mrc_alt_write_mask(DDRPHY,
				DQTCOPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
				1 << 31, 1 << 31);
			/* TCOCOMP PD */
			mrc_alt_write_mask(DDRPHY,
				DQTCOPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
				1 << 31, 1 << 31);

			/* DQS COMP Overrides */
			/* RCOMP PU */
			mrc_alt_write_mask(DDRPHY,
				DQSDRVPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
				(1 << 31) | (0x0a << 16),
				0x801f0000);
			/* RCOMP PD */
			mrc_alt_write_mask(DDRPHY,
				DQSDRVPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
				(1 << 31) | (0x0a << 16),
				0x801f0000);
			/* DCOMP PU */
			mrc_alt_write_mask(DDRPHY,
				DQSDLYPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
				(1 << 31) | (0x10 << 16),
				0x801f0000);
			/* DCOMP PD */
			mrc_alt_write_mask(DDRPHY,
				DQSDLYPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
				(1 << 31) | (0x10 << 16),
				0x801f0000);
			/* ODTCOMP PU */
			mrc_alt_write_mask(DDRPHY,
				DQSODTPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
				(1 << 31) | (0x0b << 16),
				0x801f0000);
			/* ODTCOMP PD */
			mrc_alt_write_mask(DDRPHY,
				DQSODTPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
				(1 << 31) | (0x0b << 16),
				0x801f0000);
			/* TCOCOMP PU */
			mrc_alt_write_mask(DDRPHY,
				DQSTCOPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
				1 << 31, 1 << 31);
			/* TCOCOMP PD */
			mrc_alt_write_mask(DDRPHY,
				DQSTCOPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
				1 << 31, 1 << 31);

			/* CLK COMP Overrides */
			/* RCOMP PU */
			mrc_alt_write_mask(DDRPHY,
				CLKDRVPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
				(1 << 31) | (0x0c << 16),
				0x801f0000);
			/* RCOMP PD */
			mrc_alt_write_mask(DDRPHY,
				CLKDRVPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
				(1 << 31) | (0x0c << 16),
				0x801f0000);
			/* DCOMP PU */
			mrc_alt_write_mask(DDRPHY,
				CLKDLYPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
				(1 << 31) | (0x07 << 16),
				0x801f0000);
			/* DCOMP PD */
			mrc_alt_write_mask(DDRPHY,
				CLKDLYPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
				(1 << 31) | (0x07 << 16),
				0x801f0000);
			/* ODTCOMP PU */
			mrc_alt_write_mask(DDRPHY,
				CLKODTPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
				(1 << 31) | (0x0b << 16),
				0x801f0000);
			/* ODTCOMP PD */
			mrc_alt_write_mask(DDRPHY,
				CLKODTPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
				(1 << 31) | (0x0b << 16),
				0x801f0000);
			/* TCOCOMP PU */
			mrc_alt_write_mask(DDRPHY,
				CLKTCOPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
				1 << 31, 1 << 31);
			/* TCOCOMP PD */
			mrc_alt_write_mask(DDRPHY,
				CLKTCOPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
				1 << 31, 1 << 31);

			/* CMD COMP Overrides */
			/* RCOMP PU */
			mrc_alt_write_mask(DDRPHY,
				CMDDRVPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
				(1 << 31) | (0x0d << 16),
				0x803f0000);
			/* RCOMP PD */
			mrc_alt_write_mask(DDRPHY,
				CMDDRVPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
				(1 << 31) | (0x0d << 16),
				0x803f0000);
			/* DCOMP PU */
			mrc_alt_write_mask(DDRPHY,
				CMDDLYPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
				(1 << 31) | (0x0a << 16),
				0x801f0000);
			/* DCOMP PD */
			mrc_alt_write_mask(DDRPHY,
				CMDDLYPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
				(1 << 31) | (0x0a << 16),
				0x801f0000);

			/* CTL COMP Overrides */
			/* RCOMP PU */
			mrc_alt_write_mask(DDRPHY,
				CTLDRVPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
				(1 << 31) | (0x0d << 16),
				0x803f0000);
			/* RCOMP PD */
			mrc_alt_write_mask(DDRPHY,
				CTLDRVPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
				(1 << 31) | (0x0d << 16),
				0x803f0000);
			/* DCOMP PU */
			mrc_alt_write_mask(DDRPHY,
				CTLDLYPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
				(1 << 31) | (0x0a << 16),
				0x801f0000);
			/* DCOMP PD */
			mrc_alt_write_mask(DDRPHY,
				CTLDLYPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
				(1 << 31) | (0x0a << 16),
				0x801f0000);
#else
			/* DQ TCOCOMP Overrides */
			/* TCOCOMP PU */
			mrc_alt_write_mask(DDRPHY,
				DQTCOPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
				(1 << 31) | (0x1f << 16),
				0x801f0000);
			/* TCOCOMP PD */
			mrc_alt_write_mask(DDRPHY,
				DQTCOPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
				(1 << 31) | (0x1f << 16),
				0x801f0000);

			/* DQS TCOCOMP Overrides */
			/* TCOCOMP PU */
			mrc_alt_write_mask(DDRPHY,
				DQSTCOPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
				(1 << 31) | (0x1f << 16),
				0x801f0000);
			/* TCOCOMP PD */
			mrc_alt_write_mask(DDRPHY,
				DQSTCOPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
				(1 << 31) | (0x1f << 16),
				0x801f0000);

			/* CLK TCOCOMP Overrides */
			/* TCOCOMP PU */
			mrc_alt_write_mask(DDRPHY,
				CLKTCOPUCTLCH0 + ch * DDRCOMP_CH_OFFSET,
				(1 << 31) | (0x1f << 16),
				0x801f0000);
			/* TCOCOMP PD */
			mrc_alt_write_mask(DDRPHY,
				CLKTCOPDCTLCH0 + ch * DDRCOMP_CH_OFFSET,
				(1 << 31) | (0x1f << 16),
				0x801f0000);
#endif

			/* program STATIC delays */
#ifdef BACKUP_WCMD
			set_wcmd(ch, ddr_wcmd[PLATFORM_ID]);
#else
			set_wcmd(ch, ddr_wclk[PLATFORM_ID] + HALF_CLK);
#endif

			for (rk = 0; rk < NUM_RANKS; rk++) {
				if (mrc_params->rank_enables & (1 << rk)) {
					set_wclk(ch, rk, ddr_wclk[PLATFORM_ID]);
#ifdef BACKUP_WCTL
					set_wctl(ch, rk, ddr_wctl[PLATFORM_ID]);
#else
					set_wctl(ch, rk, ddr_wclk[PLATFORM_ID] + HALF_CLK);
#endif
				}
			}
		}
	}

	/* COMP (non channel specific) */
	/* RCOMP: Dither PU Enable */
	mrc_alt_write_mask(DDRPHY, DQANADRVPUCTL, 1 << 30, 1 << 30);
	/* RCOMP: Dither PD Enable */
	mrc_alt_write_mask(DDRPHY, DQANADRVPDCTL, 1 << 30, 1 << 30);
	/* RCOMP: Dither PU Enable */
	mrc_alt_write_mask(DDRPHY, CMDANADRVPUCTL, 1 << 30, 1 << 30);
	/* RCOMP: Dither PD Enable */
	mrc_alt_write_mask(DDRPHY, CMDANADRVPDCTL, 1 << 30, 1 << 30);
	/* RCOMP: Dither PU Enable */
	mrc_alt_write_mask(DDRPHY, CLKANADRVPUCTL, 1 << 30, 1 << 30);
	/* RCOMP: Dither PD Enable */
	mrc_alt_write_mask(DDRPHY, CLKANADRVPDCTL, 1 << 30, 1 << 30);
	/* RCOMP: Dither PU Enable */
	mrc_alt_write_mask(DDRPHY, DQSANADRVPUCTL, 1 << 30, 1 << 30);
	/* RCOMP: Dither PD Enable */
	mrc_alt_write_mask(DDRPHY, DQSANADRVPDCTL, 1 << 30, 1 << 30);
	/* RCOMP: Dither PU Enable */
	mrc_alt_write_mask(DDRPHY, CTLANADRVPUCTL, 1 << 30, 1 << 30);
	/* RCOMP: Dither PD Enable */
	mrc_alt_write_mask(DDRPHY, CTLANADRVPDCTL, 1 << 30, 1 << 30);
	/* ODT: Dither PU Enable */
	mrc_alt_write_mask(DDRPHY, DQANAODTPUCTL, 1 << 30, 1 << 30);
	/* ODT: Dither PD Enable */
	mrc_alt_write_mask(DDRPHY, DQANAODTPDCTL, 1 << 30, 1 << 30);
	/* ODT: Dither PU Enable */
	mrc_alt_write_mask(DDRPHY, CLKANAODTPUCTL, 1 << 30, 1 << 30);
	/* ODT: Dither PD Enable */
	mrc_alt_write_mask(DDRPHY, CLKANAODTPDCTL, 1 << 30, 1 << 30);
	/* ODT: Dither PU Enable */
	mrc_alt_write_mask(DDRPHY, DQSANAODTPUCTL, 1 << 30, 1 << 30);
	/* ODT: Dither PD Enable */
	mrc_alt_write_mask(DDRPHY, DQSANAODTPDCTL, 1 << 30, 1 << 30);
	/* DCOMP: Dither PU Enable */
	mrc_alt_write_mask(DDRPHY, DQANADLYPUCTL, 1 << 30, 1 << 30);
	/* DCOMP: Dither PD Enable */
	mrc_alt_write_mask(DDRPHY, DQANADLYPDCTL, 1 << 30, 1 << 30);
	/* DCOMP: Dither PU Enable */
	mrc_alt_write_mask(DDRPHY, CMDANADLYPUCTL, 1 << 30, 1 << 30);
	/* DCOMP: Dither PD Enable */
	mrc_alt_write_mask(DDRPHY, CMDANADLYPDCTL, 1 << 30, 1 << 30);
	/* DCOMP: Dither PU Enable */
	mrc_alt_write_mask(DDRPHY, CLKANADLYPUCTL, 1 << 30, 1 << 30);
	/* DCOMP: Dither PD Enable */
	mrc_alt_write_mask(DDRPHY, CLKANADLYPDCTL, 1 << 30, 1 << 30);
	/* DCOMP: Dither PU Enable */
	mrc_alt_write_mask(DDRPHY, DQSANADLYPUCTL, 1 << 30, 1 << 30);
	/* DCOMP: Dither PD Enable */
	mrc_alt_write_mask(DDRPHY, DQSANADLYPDCTL, 1 << 30, 1 << 30);
	/* DCOMP: Dither PU Enable */
	mrc_alt_write_mask(DDRPHY, CTLANADLYPUCTL, 1 << 30, 1 << 30);
	/* DCOMP: Dither PD Enable */
	mrc_alt_write_mask(DDRPHY, CTLANADLYPDCTL, 1 << 30, 1 << 30);
	/* TCO: Dither PU Enable */
	mrc_alt_write_mask(DDRPHY, DQANATCOPUCTL, 1 << 30, 1 << 30);
	/* TCO: Dither PD Enable */
	mrc_alt_write_mask(DDRPHY, DQANATCOPDCTL, 1 << 30, 1 << 30);
	/* TCO: Dither PU Enable */
	mrc_alt_write_mask(DDRPHY, CLKANATCOPUCTL, 1 << 30, 1 << 30);
	/* TCO: Dither PD Enable */
	mrc_alt_write_mask(DDRPHY, CLKANATCOPDCTL, 1 << 30, 1 << 30);
	/* TCO: Dither PU Enable */
	mrc_alt_write_mask(DDRPHY, DQSANATCOPUCTL, 1 << 30, 1 << 30);
	/* TCO: Dither PD Enable */
	mrc_alt_write_mask(DDRPHY, DQSANATCOPDCTL, 1 << 30, 1 << 30);
	/* TCOCOMP: Pulse Count */
	mrc_alt_write_mask(DDRPHY, TCOCNTCTRL, 1, 3);
	/* ODT: CMD/CTL PD/PU */
	mrc_alt_write_mask(DDRPHY, CHNLBUFSTATIC,
		(0x03 << 24) | (0x03 << 16), 0x1f1f0000);
	/* Set 1us counter */
	mrc_alt_write_mask(DDRPHY, MSCNTR, 0x64, 0xff);
	mrc_alt_write_mask(DDRPHY, LATCH1CTL, 0x1 << 28, 0x70000000);

	/* Release PHY from reset */
	mrc_alt_write_mask(DDRPHY, MASTERRSTN, 1, 1);

	/* STEP1 */
	mrc_post_code(0x03, 0x11);

	for (ch = 0; ch < NUM_CHANNELS; ch++) {
		if (mrc_params->channel_enables & (1 << ch)) {
			/* DQ01-DQ23 */
			for (bl_grp = 0;
			     bl_grp < (NUM_BYTE_LANES / bl_divisor) / 2;
			     bl_grp++) {
				mrc_alt_write_mask(DDRPHY,
					DQMDLLCTL +
					bl_grp * DDRIODQ_BL_OFFSET +
					ch * DDRIODQ_CH_OFFSET,
					1 << 13,
					1 << 13);	/* Enable VREG */
				delay_n(3);
			}

			/* ECC */
			mrc_alt_write_mask(DDRPHY, ECCMDLLCTL,
				1 << 13, 1 << 13);	/* Enable VREG */
			delay_n(3);
			/* CMD */
			mrc_alt_write_mask(DDRPHY,
				CMDMDLLCTL + ch * DDRIOCCC_CH_OFFSET,
				1 << 13, 1 << 13);	/* Enable VREG */
			delay_n(3);
			/* CLK-CTL */
			mrc_alt_write_mask(DDRPHY,
				CCMDLLCTL + ch * DDRIOCCC_CH_OFFSET,
				1 << 13, 1 << 13);	/* Enable VREG */
			delay_n(3);
		}
	}

	/* STEP2 */
	mrc_post_code(0x03, 0x12);
	delay_n(200);

	for (ch = 0; ch < NUM_CHANNELS; ch++) {
		if (mrc_params->channel_enables & (1 << ch)) {
			/* DQ01-DQ23 */
			for (bl_grp = 0;
			     bl_grp < (NUM_BYTE_LANES / bl_divisor) / 2;
			     bl_grp++) {
				mrc_alt_write_mask(DDRPHY,
					DQMDLLCTL +
					bl_grp * DDRIODQ_BL_OFFSET +
					ch * DDRIODQ_CH_OFFSET,
					1 << 17,
					1 << 17);	/* Enable MCDLL */
				delay_n(50);
			}

		/* ECC */
		mrc_alt_write_mask(DDRPHY, ECCMDLLCTL,
			1 << 17, 1 << 17);	/* Enable MCDLL */
		delay_n(50);
		/* CMD */
		mrc_alt_write_mask(DDRPHY,
			CMDMDLLCTL + ch * DDRIOCCC_CH_OFFSET,
			1 << 18, 1 << 18);	/* Enable MCDLL */
		delay_n(50);
		/* CLK-CTL */
		mrc_alt_write_mask(DDRPHY,
			CCMDLLCTL + ch * DDRIOCCC_CH_OFFSET,
			1 << 18, 1 << 18);	/* Enable MCDLL */
		delay_n(50);
		}
	}

	/* STEP3: */
	mrc_post_code(0x03, 0x13);
	delay_n(100);

	for (ch = 0; ch < NUM_CHANNELS; ch++) {
		if (mrc_params->channel_enables & (1 << ch)) {
			/* DQ01-DQ23 */
			for (bl_grp = 0;
			     bl_grp < (NUM_BYTE_LANES / bl_divisor) / 2;
			     bl_grp++) {
#ifdef FORCE_16BIT_DDRIO
				temp = (bl_grp &&
					(mrc_params->channel_width == X16)) ?
					0x11ff : 0xffff;
#else
				temp = 0xffff;
#endif
				/* Enable TXDLL */
				mrc_alt_write_mask(DDRPHY,
					DQDLLTXCTL +
					bl_grp * DDRIODQ_BL_OFFSET +
					ch * DDRIODQ_CH_OFFSET,
					temp, 0xffff);
				delay_n(3);
				/* Enable RXDLL */
				mrc_alt_write_mask(DDRPHY,
					DQDLLRXCTL +
					bl_grp * DDRIODQ_BL_OFFSET +
					ch * DDRIODQ_CH_OFFSET,
					0xf, 0xf);
				delay_n(3);
				/* Enable RXDLL Overrides BL0 */
				mrc_alt_write_mask(DDRPHY,
					B0OVRCTL +
					bl_grp * DDRIODQ_BL_OFFSET +
					ch * DDRIODQ_CH_OFFSET,
					0xf, 0xf);
			}

			/* ECC */
			temp = 0xffff;
			mrc_alt_write_mask(DDRPHY, ECCDLLTXCTL,
				temp, 0xffff);
			delay_n(3);

			/* CMD (PO) */
			mrc_alt_write_mask(DDRPHY,
				CMDDLLTXCTL + ch * DDRIOCCC_CH_OFFSET,
				temp, 0xffff);
			delay_n(3);
		}
	}

	/* STEP4 */
	mrc_post_code(0x03, 0x14);

	for (ch = 0; ch < NUM_CHANNELS; ch++) {
		if (mrc_params->channel_enables & (1 << ch)) {
			/* Host To Memory Clock Alignment (HMC) for 800/1066 */
			for (bl_grp = 0;
			     bl_grp < (NUM_BYTE_LANES / bl_divisor) / 2;
			     bl_grp++) {
				/* CLK_ALIGN_MOD_ID */
				mrc_alt_write_mask(DDRPHY,
					DQCLKALIGNREG2 +
					bl_grp * DDRIODQ_BL_OFFSET +
					ch * DDRIODQ_CH_OFFSET,
					bl_grp ? 3 : 1,
					0xf);
			}

			mrc_alt_write_mask(DDRPHY,
				ECCCLKALIGNREG2 + ch * DDRIODQ_CH_OFFSET,
				0x2, 0xf);
			mrc_alt_write_mask(DDRPHY,
				CMDCLKALIGNREG2 + ch * DDRIODQ_CH_OFFSET,
				0x0, 0xf);
			mrc_alt_write_mask(DDRPHY,
				CCCLKALIGNREG2 + ch * DDRIODQ_CH_OFFSET,
				0x2, 0xf);
			mrc_alt_write_mask(DDRPHY,
				CMDCLKALIGNREG0 + ch * DDRIOCCC_CH_OFFSET,
				0x20, 0x30);
			/*
			 * NUM_SAMPLES, MAX_SAMPLES,
			 * MACRO_PI_STEP, MICRO_PI_STEP
			 */
			mrc_alt_write_mask(DDRPHY,
				CMDCLKALIGNREG1 + ch * DDRIOCCC_CH_OFFSET,
				(0x18 << 16) | (0x10 << 8) |
				(0x8 << 2) | (0x1 << 0),
				0x007f7fff);
			/* TOTAL_NUM_MODULES, FIRST_U_PARTITION */
			mrc_alt_write_mask(DDRPHY,
				CMDCLKALIGNREG2 + ch * DDRIOCCC_CH_OFFSET,
				(0x10 << 16) | (0x4 << 8) | (0x2 << 4),
				0x001f0ff0);
#ifdef HMC_TEST
			/* START_CLK_ALIGN=1 */
			mrc_alt_write_mask(DDRPHY,
				CMDCLKALIGNREG0 + ch * DDRIOCCC_CH_OFFSET,
				1 << 24, 1 << 24);
			while (msg_port_alt_read(DDRPHY,
				CMDCLKALIGNREG0 + ch * DDRIOCCC_CH_OFFSET) &
				(1 << 24))
				;	/* wait for START_CLK_ALIGN=0 */
#endif

			/* Set RD/WR Pointer Seperation & COUNTEN & FIFOPTREN */
			mrc_alt_write_mask(DDRPHY,
				CMDPTRREG + ch * DDRIOCCC_CH_OFFSET,
				1, 1);	/* WRPTRENABLE=1 */

			/* COMP initial */
			/* enable bypass for CLK buffer (PO) */
			mrc_alt_write_mask(DDRPHY,
				COMPEN0CH0 + ch * DDRCOMP_CH_OFFSET,
				1 << 5, 1 << 5);
			/* Initial COMP Enable */
			mrc_alt_write_mask(DDRPHY, CMPCTRL, 1, 1);
			/* wait for Initial COMP Enable = 0 */
			while (msg_port_alt_read(DDRPHY, CMPCTRL) & 1)
				;
			/* disable bypass for CLK buffer (PO) */
			mrc_alt_write_mask(DDRPHY,
				COMPEN0CH0 + ch * DDRCOMP_CH_OFFSET,
				~(1 << 5), 1 << 5);

			/* IOBUFACT */

			/* STEP4a */
			mrc_alt_write_mask(DDRPHY,
				CMDCFGREG0 + ch * DDRIOCCC_CH_OFFSET,
				1 << 2, 1 << 2);	/* IOBUFACTRST_N=1 */

			/* DDRPHY initialization complete */
			mrc_alt_write_mask(DDRPHY,
				CMDPMCONFIG0 + ch * DDRIOCCC_CH_OFFSET,
				1 << 20, 1 << 20);	/* SPID_INIT_COMPLETE=1 */
		}
	}

	LEAVEFN();
}