/*
 * This file is part of the coreboot project.
 *
 * Copyright (C) 2010 Advanced Micro Devices, Inc.
 * Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2 of the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

static void FreqChgCtrlWrd(struct MCTStatStruc *pMCTstat,
			struct DCTStatStruc *pDCTstat);


static void AgesaDelay(u32 msec)
{
	mct_Wait(msec*10);
}

void PrepareC_MCT(struct MCTStatStruc *pMCTstat,
					struct DCTStatStruc *pDCTstat)
{
	pDCTstat->C_MCTPtr->AgesaDelay = AgesaDelay;
	pDCTstat->C_MCTPtr->PlatMaxTotalDimms = mctGet_NVbits(NV_MAX_DIMMS);
	pDCTstat->C_MCTPtr->PlatMaxDimmsDct = pDCTstat->C_MCTPtr->PlatMaxTotalDimms >> 1;
}

void PrepareC_DCT(struct MCTStatStruc *pMCTstat,
					struct DCTStatStruc *pDCTstat, u8 dct)
{
	u8 dimm;
	u16 DimmValid;
	u16 Dimmx8Present;

	dct &= 1;

	pDCTstat->C_DCTPtr[dct]->DctTrain = dct;

	if (dct == 1) {
		Dimmx8Present = pDCTstat->Dimmx8Present >> 1;
	} else
		Dimmx8Present = pDCTstat->Dimmx8Present;
	Dimmx8Present &= 0x55;

	pDCTstat->C_DCTPtr[dct]->MaxDimmsInstalled = pDCTstat->MAdimms[dct];
	DimmValid = pDCTstat->DIMMValidDCT[dct];

	pDCTstat->C_DCTPtr[dct]->NodeId = pDCTstat->Node_ID;
	pDCTstat->C_DCTPtr[dct]->LogicalCPUID = pDCTstat->LogicalCPUID;

	for (dimm = 0; dimm < MAX_DIMMS; dimm++) {
		if (DimmValid & (1 << (dimm << 1)))
			pDCTstat->C_DCTPtr[dct]->DimmPresent[dimm] = 1;
		if (Dimmx8Present & (1 << (dimm << 1)))
			pDCTstat->C_DCTPtr[dct]->DimmX8Present[dimm] = 1;
	}

	if (pDCTstat->GangedMode & (1 << 0))
		pDCTstat->C_DCTPtr[dct]->CurrDct = 0;
	else
		pDCTstat->C_DCTPtr[dct]->CurrDct = dct;

	pDCTstat->C_DCTPtr[dct]->DctCSPresent = pDCTstat->CSPresent_DCT[dct];
	if (!(pDCTstat->GangedMode & (1 << 0)) && (dct == 1))
		pDCTstat->C_DCTPtr[dct]->DctCSPresent = pDCTstat->CSPresent_DCT[0];

	if (pDCTstat->Status & (1 << SB_Registered)) {
		pDCTstat->C_DCTPtr[dct]->Status[DCT_STATUS_REGISTERED] = 1;
		pDCTstat->C_DCTPtr[dct]->Status[DCT_STATUS_OnDimmMirror] = 0;
	} else {
		if (pDCTstat->MirrPresU_NumRegR > 0)
			pDCTstat->C_DCTPtr[dct]->Status[DCT_STATUS_OnDimmMirror] = 1;
		pDCTstat->C_DCTPtr[dct]->Status[DCT_STATUS_REGISTERED] = 0;
	}

	if (pDCTstat->Status & (1 << SB_LoadReduced)) {
		pDCTstat->C_DCTPtr[dct]->Status[DCT_STATUS_LOAD_REDUCED] = 1;
	} else {
		pDCTstat->C_DCTPtr[dct]->Status[DCT_STATUS_LOAD_REDUCED] = 0;
	}

	pDCTstat->C_DCTPtr[dct]->RegMan1Present = pDCTstat->RegMan1Present;

	for (dimm = 0; dimm < MAX_TOTAL_DIMMS; dimm++) {
		u8  DimmRanks;
		if (DimmValid & (1 << (dimm << 1))) {
			DimmRanks = 1;
			if (pDCTstat->DimmDRPresent & (1 << ((dimm << 1) + dct)))
				DimmRanks = 2;
			else if (pDCTstat->DimmQRPresent & (1 << ((dimm << 1) + dct)))
				DimmRanks = 4;
		} else
			DimmRanks = 0;
		pDCTstat->C_DCTPtr[dct]->DimmRanks[dimm] = DimmRanks;
	}
}

void EnableZQcalibration(struct MCTStatStruc *pMCTstat, struct DCTStatStruc *pDCTstat)
{
	u32 val;

	val = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x94);
	val |= 1 << 11;
	Set_NB32_DCT(pDCTstat->dev_dct, 0, 0x94, val);

	val = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x94);
	val |= 1 << 11;
	Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x94, val);
}

void DisableZQcalibration(struct MCTStatStruc *pMCTstat,
					struct DCTStatStruc *pDCTstat)
{
	u32 val;

	val = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x94);
	val &= ~(1 << 11);
	val &= ~(1 << 10);
	Set_NB32_DCT(pDCTstat->dev_dct, 0, 0x94, val);

	val = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x94);
	val &= ~(1 << 11);
	val &= ~(1 << 10);
	Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x94, val);
}

static void EnterSelfRefresh(struct MCTStatStruc *pMCTstat,
					struct DCTStatStruc *pDCTstat)
{
	u8 DCT0Present, DCT1Present;
	u32 val;

	DCT0Present = pDCTstat->DIMMValidDCT[0];
	if (pDCTstat->GangedMode)
		DCT1Present = 0;
	else
		DCT1Present = pDCTstat->DIMMValidDCT[1];

	/* Program F2x[1, 0]90[EnterSelfRefresh]=1. */
	if (DCT0Present) {
		val = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x90);
		val |= 1 << EnterSelfRef;
		Set_NB32_DCT(pDCTstat->dev_dct, 0, 0x90, val);
	}
	if (DCT1Present) {
		val = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x90);
		val |= 1 << EnterSelfRef;
		Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x90, val);
	}
	/* Wait until the hardware resets F2x[1, 0]90[EnterSelfRefresh]=0. */
	if (DCT0Present)
		do {
			val = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x90);
		} while (val & (1 <<EnterSelfRef));
	if (DCT1Present)
		do {
			val = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x90);
		} while (val & (1 <<EnterSelfRef));
}

/*
 * Change memclk for write levelization pass 2
 */
static void ChangeMemClk(struct MCTStatStruc *pMCTstat,
					struct DCTStatStruc *pDCTstat)
{
	uint8_t DCT0Present;
	uint8_t DCT1Present;
	uint32_t dword;
	uint32_t mask;
	uint32_t offset;

	DCT0Present = pDCTstat->DIMMValidDCT[0];
	if (pDCTstat->GangedMode)
		DCT1Present = 0;
	else
		DCT1Present = pDCTstat->DIMMValidDCT[1];

	if (is_fam15h()) {
		/* Program D18F2x9C_x0D0F_E006_dct[1:0][PllLockTime] = 0x190 */
		if (DCT0Present) {
			dword = Get_NB32_index_wait_DCT(pDCTstat->dev_dct, 0, 0x98, 0x0d0fe006);
			dword &= ~(0x0000ffff);
			dword |= 0x00000190;
			Set_NB32_index_wait_DCT(pDCTstat->dev_dct, 0, 0x98, 0x0d0fe006, dword);
		}
		if (DCT1Present) {
			dword = Get_NB32_index_wait_DCT(pDCTstat->dev_dct, 1, 0x98, 0x0d0fe006);
			dword &= ~(0x0000ffff);
			dword |= 0x00000190;
			Set_NB32_index_wait_DCT(pDCTstat->dev_dct, 1, 0x98, 0x0d0fe006, dword);
		}
	} else {
		/* Program F2x[1, 0]9C[DisAutoComp]=1. */
		if (DCT0Present) {
			dword = Get_NB32_index_wait_DCT(pDCTstat->dev_dct, 0, 0x98, 8);
			dword |= 1 << DisAutoComp;
			Set_NB32_index_wait_DCT(pDCTstat->dev_dct, 0, 0x98, 8, dword);
			mct_Wait(100);	/* Wait for 5us */
		}
		if (DCT1Present) {
			dword = Get_NB32_index_wait_DCT(pDCTstat->dev_dct, 1, 0x98, 8);
			dword |= 1 << DisAutoComp;
			Set_NB32_index_wait_DCT(pDCTstat->dev_dct, 1, 0x98, 8, dword);
			mct_Wait(100);	/* Wait for 5us */
		}
	}

	/* Program F2x[1, 0]94[MemClkFreqVal] = 0. */
	if (DCT0Present) {
		dword = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x94);
		dword &= ~(1 << MemClkFreqVal);
		Set_NB32_DCT(pDCTstat->dev_dct, 0, 0x94, dword);
	}
	if (DCT1Present) {
		dword = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x94);
		dword &= ~(1 << MemClkFreqVal);
		Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x94, dword);
	}

	/* Program F2x[1, 0]94[MemClkFreq] to specify the target MEMCLK frequency. */
	if (is_fam15h()) {
		offset = 0x0;
		mask = 0x1f;
	} else {
		offset = 0x1;
		mask = 0x7;
	}
	if (DCT0Present) {
		dword = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x94);
		dword &= ~mask;
		dword |= (pDCTstat->TargetFreq - offset) & mask;
		Set_NB32_DCT(pDCTstat->dev_dct, 0, 0x94, dword);
	}
	if (DCT1Present) {
		dword = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x94);
		dword &= ~mask;
		dword |= (pDCTstat->TargetFreq - offset) & mask;
		Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x94, dword);
	}

	if (is_fam15h()) {
		if (DCT0Present) {
			mctGet_PS_Cfg_D(pMCTstat, pDCTstat, 0);
			set_2t_configuration(pMCTstat, pDCTstat, 0);
			mct_BeforePlatformSpec(pMCTstat, pDCTstat, 0);
			mct_PlatformSpec(pMCTstat, pDCTstat, 0);
		}
		if (DCT1Present) {
			mctGet_PS_Cfg_D(pMCTstat, pDCTstat, 1);
			set_2t_configuration(pMCTstat, pDCTstat, 1);
			mct_BeforePlatformSpec(pMCTstat, pDCTstat, 1);
			mct_PlatformSpec(pMCTstat, pDCTstat, 1);
		}
	}

	/* Program F2x[1, 0]94[MemClkFreqVal] = 1. */
	if (DCT0Present) {
		dword = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x94);
		dword |= 1 << MemClkFreqVal;
		Set_NB32_DCT(pDCTstat->dev_dct, 0, 0x94, dword);
	}
	if (DCT1Present) {
		dword = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x94);
		dword |= 1 << MemClkFreqVal;
		Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x94, dword);
	}

	/* Wait until F2x[1, 0]94[FreqChgInProg]=0. */
	if (DCT0Present)
		do {
			dword = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x94);
		} while (dword & (1 << FreqChgInProg));
	if (DCT1Present)
		do {
			dword = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x94);
		} while (dword & (1 << FreqChgInProg));

	if (is_fam15h()) {
		/* Program D18F2x9C_x0D0F_E006_dct[1:0][PllLockTime] = 0xf */
		if (DCT0Present) {
			dword = Get_NB32_index_wait_DCT(pDCTstat->dev_dct, 0, 0x98, 0x0d0fe006);
			dword &= ~(0x0000ffff);
			dword |= 0x0000000f;
			Set_NB32_index_wait_DCT(pDCTstat->dev_dct, 0, 0x98, 0x0d0fe006, dword);
		}
		if (DCT1Present) {
			dword = Get_NB32_index_wait_DCT(pDCTstat->dev_dct, 1, 0x98, 0x0d0fe006);
			dword &= ~(0x0000ffff);
			dword |= 0x0000000f;
			Set_NB32_index_wait_DCT(pDCTstat->dev_dct, 1, 0x98, 0x0d0fe006, dword);
		}
	} else {
		/* Program F2x[1, 0]9C[DisAutoComp] = 0. */
		if (DCT0Present) {
			dword = Get_NB32_index_wait_DCT(pDCTstat->dev_dct, 0, 0x98, 8);
			dword &= ~(1 << DisAutoComp);
			Set_NB32_index_wait_DCT(pDCTstat->dev_dct, 0, 0x98, 8, dword);
			mct_Wait(15000);	/* Wait for 750us */
		}
		if (DCT1Present) {
			dword = Get_NB32_index_wait_DCT(pDCTstat->dev_dct, 1, 0x98, 8);
			dword &= ~(1 << DisAutoComp);
			Set_NB32_index_wait_DCT(pDCTstat->dev_dct, 1, 0x98, 8, dword);
			mct_Wait(15000);	/* Wait for 750us */
		}
	}
}

/*
 * the DRAM controller to bring the DRAMs out of self refresh mode.
 */
static void ExitSelfRefresh(struct MCTStatStruc *pMCTstat,
					struct DCTStatStruc *pDCTstat)
{
	u8 DCT0Present, DCT1Present;
	u32 val;

	DCT0Present = pDCTstat->DIMMValidDCT[0];
	if (pDCTstat->GangedMode)
		DCT1Present = 0;
	else
		DCT1Present = pDCTstat->DIMMValidDCT[1];

	/* Program F2x[1, 0]90[ExitSelfRef]=1 for both DCTs. */
	if (DCT0Present) {
		val = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x90);
		val |= 1 << ExitSelfRef;
		Set_NB32_DCT(pDCTstat->dev_dct, 0, 0x90, val);
	}
	if (DCT1Present) {
		val = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x90);
		val |= 1 << ExitSelfRef;
		Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x90, val);
	}
	/* Wait until the hardware resets F2x[1, 0]90[ExitSelfRef]=0. */
	if (DCT0Present)
		do {
			val = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x90);
		} while (val & (1 << ExitSelfRef));
	if (DCT1Present)
		do {
			val = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x90);
		} while (val & (1 << ExitSelfRef));
}

void SetTargetFreq(struct MCTStatStruc *pMCTstat,
					struct DCTStatStruc *pDCTstat)
{
	uint32_t dword;
	uint8_t package_type = mctGet_NVbits(NV_PACK_TYPE);

	if (is_fam15h()) {
		/* Program F2x[1, 0]90[DisDllShutDownSR]=1. */
		if (pDCTstat->DIMMValidDCT[0]) {
			dword = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x90);
			dword |= (0x1 << 27);
			Set_NB32_DCT(pDCTstat->dev_dct, 0, 0x90, dword);
		}
		if (pDCTstat->DIMMValidDCT[1]) {
			dword = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x90);
			dword |= (0x1 << 27);
			Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x90, dword);
		}
	}

	/* Program F2x[1,0]90[EnterSelfRefresh]=1.
	 * Wait until the hardware resets F2x[1,0]90[EnterSelfRefresh]=0.
	 */
	EnterSelfRefresh(pMCTstat, pDCTstat);

	/*
	 * Program F2x[1,0]9C_x08[DisAutoComp]=1
	 * Program F2x[1,0]94[MemClkFreqVal] = 0.
	 * Program F2x[1,0]94[MemClkFreq] to specify the target MEMCLK frequency.
	 * Program F2x[1,0]94[MemClkFreqVal] = 1.
	 * Wait until F2x[1,0]94[FreqChgInProg]=0.
	 * Program F2x[1,0]9C_x08[DisAutoComp]=0
	 */
	ChangeMemClk(pMCTstat, pDCTstat);

	if (is_fam15h()) {
		uint8_t dct;
		for (dct = 0; dct < 2; dct++) {
			if (pDCTstat->DIMMValidDCT[dct]) {
				phyAssistedMemFnceTraining(pMCTstat, pDCTstat);
				InitPhyCompensation(pMCTstat, pDCTstat, dct);
			}
		}
	}

	/* Program F2x[1,0]90[ExitSelfRef]=1 for both DCTs.
	 * Wait until the hardware resets F2x[1, 0]90[ExitSelfRef]=0.
	 */
	ExitSelfRefresh(pMCTstat, pDCTstat);

	if (is_fam15h()) {
		if ((package_type == PT_C3) || (package_type == PT_GR)) {
			/* Socket C32 or G34 */
			/* Program F2x[1, 0]90[DisDllShutDownSR]=0. */
			if (pDCTstat->DIMMValidDCT[0]) {
				dword = Get_NB32_DCT(pDCTstat->dev_dct, 0, 0x90);
				dword &= ~(0x1 << 27);
				Set_NB32_DCT(pDCTstat->dev_dct, 0, 0x90, dword);
			}
			if (pDCTstat->DIMMValidDCT[1]) {
				dword = Get_NB32_DCT(pDCTstat->dev_dct, 1, 0x90);
				dword &= ~(0x1 << 27);
				Set_NB32_DCT(pDCTstat->dev_dct, 1, 0x90, dword);
			}
		}
	}

	/* wait for 500 MCLKs after ExitSelfRef, 500*2.5ns=1250ns */
	mct_Wait(250);

	if (pDCTstat->Status & (1 << SB_Registered)) {
		u8 DCT0Present, DCT1Present;

		DCT0Present = pDCTstat->DIMMValidDCT[0];
		if (pDCTstat->GangedMode)
			DCT1Present = 0;
		else
			DCT1Present = pDCTstat->DIMMValidDCT[1];

		if (!DCT1Present)
			pDCTstat->CSPresent = pDCTstat->CSPresent_DCT[0];
		else if (pDCTstat->GangedMode)
			pDCTstat->CSPresent = 0;
		else
			pDCTstat->CSPresent = pDCTstat->CSPresent_DCT[1];

		FreqChgCtrlWrd(pMCTstat, pDCTstat);
	}
}

static void Modify_OnDimmMirror(struct DCTStatStruc *pDCTstat, u8 dct, u8 set)
{
	u32 val;
	u32 reg = 0x44;
	while (reg < 0x60) {
		val = Get_NB32_DCT(pDCTstat->dev_dct, dct, reg);
		if (val & (1 << CSEnable))
			set ? (val |= 1 << onDimmMirror) : (val &= ~(1<<onDimmMirror));
		Set_NB32_DCT(pDCTstat->dev_dct, dct, reg, val);
		reg += 8;
	}
}

void Restore_OnDimmMirror(struct MCTStatStruc *pMCTstat,
				struct DCTStatStruc *pDCTstat)
{
	if (pDCTstat->LogicalCPUID & (AMD_DR_Bx /* | AMD_RB_C0 */)) { /* We dont support RB-C0 now */
		if (pDCTstat->MirrPresU_NumRegR & 0x55)
			Modify_OnDimmMirror(pDCTstat, 0, 1); /* dct=0, set */
		if (pDCTstat->MirrPresU_NumRegR & 0xAA)
			Modify_OnDimmMirror(pDCTstat, 1, 1); /* dct=1, set */
	}
}
void Clear_OnDimmMirror(struct MCTStatStruc *pMCTstat,
				struct DCTStatStruc *pDCTstat)
{
	if (pDCTstat->LogicalCPUID & (AMD_DR_Bx /* | AMD_RB_C0 */)) { /* We dont support RB-C0 now */
		if (pDCTstat->MirrPresU_NumRegR & 0x55)
			Modify_OnDimmMirror(pDCTstat, 0, 0); /* dct=0, clear */
		if (pDCTstat->MirrPresU_NumRegR & 0xAA)
			Modify_OnDimmMirror(pDCTstat, 1, 0); /* dct=1, clear */
	}
}
