blob: e3743e0b159cab953783f3edcb6aeb48709de255 [file] [log] [blame]
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2009 One Laptop per Child, Association, Inc.
*
* 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.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
void DRAMSetVRNum(DRAM_SYS_ATTR *DramAttr, u8 PhyRank /* physical rank */,
u8 VirRank /* virtual rank */, BOOLEAN Enable);
void SetEndingAddr(DRAM_SYS_ATTR *DramAttr, u8 VirRank /* Ending address
register number indicator (INDEX */, INT8 Value /* (value)
add or subtract value to this and after banks. */);
void InitDDR2CHA(DRAM_SYS_ATTR *DramAttr);
void InitDDR2CHB(DRAM_SYS_ATTR *DramAttr);
void InitDDR2CHC(DRAM_SYS_ATTR *DramAttr);
CB_STATUS VerifyChc(void);
/*===================================================================
Function : DRAMRegInitValue()
Precondition :
Input :
DramAttr: pointer point to DRAM_SYS_ATTR which consist the DDR and Dimm information
in MotherBoard
Output : Void
Purpose : Set necessary register before DRAM initialize
===================================================================*/
static const u8 DramRegTbl[][3] = {
/* Reg AND OR */
{0x50, 0x11, 0xEE}, // DDR default MA7 for DRAM init
{0x51, 0x11, 0x60}, // DDR default MA3 for CHB init
{0x52, 0x00, 0x33}, // DDR use BA0=M17, BA1=M18,
{0x53, 0x00, 0x3F}, // DDR BA2=M19
{0x54, 0x00, 0x00}, // default PR0=VR0; PR1=VR1
{0x55, 0x00, 0x00}, // default PR2=VR2; PR3=VR3
{0x56, 0x00, 0x00}, // default PR4=VR4; PR5=VR5
{0x57, 0x00, 0x00}, // default PR4=VR4; PR5=VR5
{0x60, 0x00, 0x00}, // disable fast turn-around
{0x65, 0x00, 0xD9}, // AGP timer = 0XD; Host timer = 8;
{0x66, 0x00, 0x88}, // DRAMC Queue Size = 4; park at the last bus
// owner,Priority promotion timer = 8
{0x68, 0x00, 0x0C},
{0x69, 0xF0, 0x04}, // set RX69[3:0]=0000b
{0x6A, 0x00, 0x00}, // refresh counter
{0x6E, 0xF8, 0x80}, // must set 6E[7], or else DDR2 probe test
// will fail
/*
* In here, we not set RX70~RX74, because we just init DRAM but no
* need R/W DRAM, when we check DQS input/output delay, then we need
* R/W DRAM.
*/
// {0x79, 0x00, 0x8F },
{0x85, 0x00, 0x00},
// {0x90, 0x87, 0x78 },
// {0x91, 0x00, 0x46 },
{0x40, 0x00, 0x00},
{0, 0, 0}
};
void DRAMRegInitValue(DRAM_SYS_ATTR *DramAttr)
{
u8 Idx, CL, Data;
for (Idx = 0; DramRegTbl[Idx][0] != 0; Idx++) {
Data = pci_read_config8(MEMCTRL, DramRegTbl[Idx][0]);
Data &= DramRegTbl[Idx][1];
Data |= DramRegTbl[Idx][2];
pci_write_config8(MEMCTRL, DramRegTbl[Idx][0], Data);
}
Data = 0x80;
pci_write_config8(PCI_DEV(0, 0, 4), 0xa3, Data);
// Set DRAM controller mode. */
Data = pci_read_config8(MEMCTRL, 0x6c);
Data &= 0xFB;
if (ENABLE_CHC == 0) {
Data |= 0x4; /* Only CHA 64 bit mode */
pci_write_config8(MEMCTRL, 0x6c, Data);
} else {
Data |= 0x0; /* CHA + CHC */
pci_write_config8(MEMCTRL, 0x6c, Data);
// Data = 0xAA;
// pci_write_config8(MEMCTRL, 0xb1, Data);
// set CHB DQSB input delay, or else will meet error which
// is some byte is right but another bit is error.
Data = pci_read_config8(MEMCTRL, 0xff);
Data = (Data & 0x03) | 0x3D;
pci_write_config8(MEMCTRL, 0xff, Data);
// enable CHC RXDB[7]
// Data = pci_read_config8(MEMCTRL, 0xdb);
// Data = (Data & 0x7F) | 0x80;
// pci_write_config8(MEMCTRL, 0xdb, Data);
// rx62[2:0], CHA and CHB CL
Data = pci_read_config8(MEMCTRL, 0x62);
CL = Data & 0x07;
// If CL = 6, so I set CHB CL = 5 default.
if (CL >= 4)
CL = 3;
/* Set CHC Read CL rxDC[6:7]. */
Data = pci_read_config8(MEMCTRL, 0xdc);
Data = (Data & 0x3F) | (CL << 6);
pci_write_config8(MEMCTRL, 0xdc, Data);
/* Set CHC write CL rxDF[6:7]. */
Data = pci_read_config8(MEMCTRL, 0xdf);
Data = (Data & 0x3F) | (CL << 6);
pci_write_config8(MEMCTRL, 0xdf, Data);
/* Set CHC ODT RxDC[5:0] */
Data = pci_read_config8(MEMCTRL, 0xdc);
Data = (Data & 0xC0) | 0x03;
pci_write_config8(MEMCTRL, 0xdc, Data);
/* Set column type RXDD[6] and enable ODT PAD RXDD[7]. */
Data = pci_read_config8(MEMCTRL, 0xdd);
Data |= 0x80;
Idx = DramAttr->DimmInfo[2].SPDDataBuf[SPD_SDRAM_COL_ADDR];
if ((Idx & 0x0F) == 10)
Data |= 0x40; /* MA9~MA0 */
else
Data &= 0xBF; /* MA8~MA0 */
pci_write_config8(MEMCTRL, 0xdd, Data);
}
// Disable Read DRAM fast ready ;Rx51[7]
// Disable Read Around Write ;Rx51[6]
// Disable Consecutive Read ;RX52[1:0]
// Disable Speculative Read
}
/*===================================================================
Function : DRAMInitializeProc()
Precondition :
Input :
DramAttr: pointer point to DRAM_SYS_ATTR which consist the DDR and Dimm information
in MotherBoard
Output : Void
Purpose : DRAM initialize according to the bios porting guid
===================================================================*/
#define EXIST_TEST_PATTERN 0x55555555
#define NOT_EXIST_TEST_PATTERN 0xAAAAAAAA
static BOOLEAN ChkForExistLowBank(void)
{
u32 *Address, data32;
/* Check pattern */
Address = (u32 *) 8;
*Address = EXIST_TEST_PATTERN;
Address = (u32 *) 4;
*Address = EXIST_TEST_PATTERN;
// _asm {WBINVD}
WaitMicroSec(100);
Address = (u32 *) 8;
data32 = *Address;
if (data32 != EXIST_TEST_PATTERN)
return FALSE;
Address = (u32 *) 4;
data32 = *Address;
if (data32 != EXIST_TEST_PATTERN)
return FALSE;
/* Check not Pattern */
Address = (u32 *) 8;
*Address = NOT_EXIST_TEST_PATTERN;
Address = (u32 *) 4;
*Address = NOT_EXIST_TEST_PATTERN;
// _asm {WBINVD}
WaitMicroSec(100);
Address = (u32 *) 8;
data32 = *Address;
if (data32 != (u32) (NOT_EXIST_TEST_PATTERN))
return FALSE;
Address = (u32 *) 4;
data32 = *Address;
if (data32 != (u32) (NOT_EXIST_TEST_PATTERN))
return FALSE;
return TRUE;
}
void DRAMInitializeProc(DRAM_SYS_ATTR *DramAttr)
{
u8 shift, idx;
BOOLEAN Status;
shift = 1;
for (idx = 0; idx < MAX_RANKS; idx++) {
if ((DramAttr->RankPresentMap & shift) != 0) {
/*
* Set VR# to physical rank indicated = PR + physical
* rank enable bit.
*/
DRAMSetVRNum(DramAttr, idx, idx, TRUE);
SetEndingAddr(DramAttr, idx, 0x10); /* Assume 1G size */
if (idx < 4) /* CHA init */
InitDDR2CHA(DramAttr); // temp wjb 2007/1 only for compiling
// in the function InitDDR2,the parameter is no need
Status = ChkForExistLowBank();
if (Status == TRUE) {
PRINT_DEBUG_MEM(" S\r");
} else {
PRINT_DEBUG_MEM(" F\r");
}
/*
* Set VR# to physical rank indicated = 00h + physical
* rank enable bit.
*/
DRAMSetVRNum(DramAttr, idx, 0, FALSE);
SetEndingAddr(DramAttr, idx, -16);
}
shift <<= 1;
}
if (ENABLE_CHC)
InitDDR2CHC(DramAttr);
}
/*===================================================================
Function : DRAMSetVRNUM()
Precondition :
Input :
DramAttr: pointer point to DRAM_SYS_ATTR which consist the DDR and Dimm information
in MotherBoard
PhyRank: Physical Rank number
VirRank: Virtual Rank number
Enable: Enable/Disable Physical Rank
Output : Void
Purpose : Set virtual rank number for physical rank
Program the specific physical rank with specific virtual rank number
Program when necessary, otherwise don't touch the pr-vr-mapping registers
===================================================================*/
void DRAMSetVRNum(DRAM_SYS_ATTR *DramAttr, u8 PhyRank /* physical rank */,
u8 VirRank /* virtual rank */, BOOLEAN Enable)
{
u8 Data, AndData, OrData;
Data = pci_read_config8(MEMCTRL, (0x54 + (PhyRank >> 1)));
OrData = 0;
if (Enable)
OrData |= 0x08;
OrData |= VirRank;
if ((PhyRank & 0x01) == 0x00) {
AndData = 0x0F; // keep the value of odd rank on PR # is even(keep 1,3,5,7)
OrData <<= 4; // VR #, value to be set
} else {
AndData = 0xF0; // keep the value of even rank on PR # is odd(keep 0,2,4,6)
}
Data &= AndData;
Data |= OrData;
pci_write_config8(MEMCTRL, (0x54 + (PhyRank >> 1)), Data);
}
/*===================================================================
Function : SetEndingAddr()
Precondition :
Input :
DramAttr: pointer point to DRAM_SYS_ATTR which consist the DDR and Dimm information
in MotherBoard
VirRank: Virtual Rank number
Value: (value) add or subtract value to this and after banks
Output : Void
Purpose : Set ending address of virtual rank specified by VirRank
===================================================================*/
void SetEndingAddr(DRAM_SYS_ATTR *DramAttr, u8 VirRank /* ending address
register number indicator (INDEX */, INT8 Value /* (value)
add or subtract value to this and after banks */) {
u8 Data;
/* Read register,Rx40-Rx47(0,1,2,3,4,5,6,7) and set ending address. */
Data = pci_read_config8(MEMCTRL, 0x40 + VirRank);
Data = (u8) (Data + Value);
pci_write_config8(MEMCTRL, 0x40 + VirRank, Data);
/* Program the virank's begining address to zero. */
Data = 0x00;
pci_write_config8(MEMCTRL, 0x48 + VirRank, Data);
}
/*===================================================================
Function : InitDDR2()
Precondition :
Input :
DramAttr: pointer point to DRAM_SYS_ATTR which consist the DDR and Dimm information
in MotherBoard
Output : Void
Purpose : Initialize DDR2 by standard sequence
===================================================================*/
// DLL: Enable Reset
static const u32 CHA_MRS_DLL_150[2] = { 0x00020200, 0x00000800 }; // with 150 ohm (A17=1, A9=1), (A11=1)(cpu address)
static const u32 CHA_MRS_DLL_75[2] = { 0x00020020, 0x00000800 }; // with 75 ohm (A17=1, A5=1), (A11=1)(cpu address)
// CPU(DRAM)
// { DLL: Enable. A17(BA0)=1 and A3(MA0)=0 }
// { DLL: reset. A11(MA8)=1 }
//
// DDR2 CL=2 CL=3 CL=4 CL=5 CL=6(Burst type=interleave)(WR fine tune in code)
static const u16 CHA_DDR2_MRS_table[5] = { 0x0150, 0x01D0, 0x0250, 0x02D0, 0x350 }; // BL=4 ;Use 1X-bandwidth MA table to init DRAM
// MA11 MA10(AP) MA9
#define CHA_MRS_DDR2_TWR2 (0 << 13) + (0 << 20) + (1 << 12) // Value = 001000h
#define CHA_MRS_DDR2_TWR3 (0 << 13) + (1 << 20) + (0 << 12) // Value = 100000h
#define CHA_MRS_DDR2_TWR4 (0 << 13) + (1 << 20) + (1 << 12) // Value = 101000h
#define CHA_MRS_DDR2_TWR5 (1 << 13) + (0 << 20) + (0 << 12) // Value = 002000h
#define CHA_MRS_DDR2_TWR6 (1 << 13) + (0 << 20) + (1 << 12) // Value = 003000h
// DDR2 Twr=2 Twr=3 Twr=4 Twr=5
static const u32 CHA_DDR2_Twr_table[5] = {
CHA_MRS_DDR2_TWR2, CHA_MRS_DDR2_TWR3, CHA_MRS_DDR2_TWR4,
CHA_MRS_DDR2_TWR5, CHA_MRS_DDR2_TWR6
};
#define CHA_OCD_Exit_150ohm 0x20200 // EMRS(1), BA0=1, MA9=MA8=MA7=0,MA6=1,MA2=0 (DRAM bus address)
// A17=1, A12=A11=A10=0,A9=1 ,A5=0 (CPU address)
#define CHA_OCD_Default_150ohm 0x21E00 // EMRS(1), BA0=1, MA9=MA8=MA7=1,MA6=1,MA2=0 (DRAM bus address)
// A17=1, A12=A11=A10=1,A9=1 ,A5=0 (CPU address)
#define CHA_OCD_Exit_75ohm 0x20020 // EMRS(1), BA0=1, MA9=MA8=MA7=0,MA6=0,MA2=1 (DRAM bus address)
// A17=1, A12=A11=A10=0,A9=0 ,A5=1 (CPU address)
#define CHA_OCD_Default_75ohm 0x21C20 // EMRS(1), BA0=1, MA9=MA8=MA7=1,MA6=0,MA2=1 (DRAM bus address)
// A17=1, A12=A11=A10=1,A9=0 ,A5=1 (CPU address)
void InitDDR2CHA(DRAM_SYS_ATTR *DramAttr)
{
u8 Data, Reg6BVal, Idx, CL, BL, Twr, DimmNum;
u32 AccessAddr;
/* Step 2 */
/* Disable bank paging and multi page. */
Data = pci_read_config8(MEMCTRL, 0x69);
Data &= ~0x03;
pci_write_config8(MEMCTRL, 0x69, Data);
Reg6BVal = pci_read_config8(MEMCTRL, 0x6b);
Reg6BVal &= ~0x07;
/* Step 3 */
/* At least one NOP cycle will be issued after the 1m sec device
* deselect.
*/
Data = Reg6BVal | 0x01;
pci_write_config8(MEMCTRL, 0x6b, Data);
/* Step 4 */
/* Read a double word from any address of the DIMM. */
DimmRead(0x0);
/* Step 5 */
/*
* A minimum pause of 200u sec will be provided after the NOP.
* - <<< reduce BOOT UP time >>> -
* Loop 200us
*/
for (Idx = 0; Idx < 0x10; Idx++)
WaitMicroSec(100);
// Step 6.
// Precharge all (PALL) will be issued to the DDR.
Data = Reg6BVal | 0x02;
pci_write_config8(MEMCTRL, 0x6b, Data);
// Step7.
// Read a double word from any address of the DIMM
DimmRead(0x0);
// Step 8.
// MSR Eable will be issued to the DDR
Data = Reg6BVal | 0x03;
pci_write_config8(MEMCTRL, 0x6b, Data);
/* Step 9, 10.
*
* Check ODT value for EMRS(1) command according to ODTLookUp_TBL
* in driving_setting.c if there is one DIMM in MB's one channel,
* the DDR2's ODT is 150ohm if there is two DIMM in MB's one channel,
* the DDR2's ODT is 75 ohm.
*/
DimmNum = DramAttr->DimmNumChA;
if (DimmNum == 1) { /* DDR's ODT is 150ohm */
AccessAddr = (u32) CHA_MRS_DLL_150[0];
DimmRead(AccessAddr); /* Issue EMRS DLL Enable. */
PRINT_DEBUG_MEM("Step 9 Address ");
PRINT_DEBUG_MEM_HEX32(AccessAddr);
PRINT_DEBUG_MEM("\r");
AccessAddr = (u32) CHA_MRS_DLL_150[1];
DimmRead(AccessAddr); /* Issue MRS DLL Reset. */
PRINT_DEBUG_MEM("Step 10 Address ");
PRINT_DEBUG_MEM_HEX32(AccessAddr);
PRINT_DEBUG_MEM("\r");
} else if (DimmNum == 2) { /* DDR's ODT is 75ohm */
AccessAddr = (u32) CHA_MRS_DLL_75[0];
DimmRead(AccessAddr); /* Issue EMRS DLL Enable. */
AccessAddr = (u32) CHA_MRS_DLL_75[1];
DimmRead(AccessAddr); /* Issue MRS DLL Reset. */
} else {
PRINT_DEBUG_MEM("Dimm NUM ERROR:");
PRINT_DEBUG_MEM_HEX8(DimmNum);
PRINT_DEBUG_MEM("\r");
}
/* Step 11. Precharge all (PALL) will be issued to the DDR. */
Data = Reg6BVal | 0x02;
pci_write_config8(MEMCTRL, 0x6b, Data);
/* Step 12. Read a double word from any address of the DIMM. */
DimmRead(0x0);
/* Step 13. Execute 8 CBR refresh. */
Data = Reg6BVal | 0x04;
pci_write_config8(MEMCTRL, 0x6b, Data);
// issue 14,15 , 16
//reads and wait 100us between each read
for (Idx = 0; Idx < 8; Idx++) {
DimmRead(0x0);
WaitMicroSec(100);
}
/* Step 17. Enable MRS for MAA. */
Data = Reg6BVal | 0x03;
pci_write_config8(MEMCTRL, 0x6b, Data);
/*
* Step 18. The SDRAM parameters (Burst Length, CAS# Latency,
* Write recovery etc.)
*/
/* Burst Length: really offset Rx6c[3] */
Data = pci_read_config8(MEMCTRL, 0x6c);
BL = (Data & 0x08) >> 3;
/* CL: really offset RX62[2:0] */
Data = pci_read_config8(MEMCTRL, 0x62);
CL = Data & 0x03;
AccessAddr = (u32) (CHA_DDR2_MRS_table[CL]);
if (BL)
AccessAddr += 8;
/* Write recovery: really offset Rx63[7-5] */
Data = pci_read_config8(MEMCTRL, 0x63);
Twr = (Data & 0xE0) >> 5;
AccessAddr += CHA_DDR2_Twr_table[Twr];
// AccessAddr = 0x1012D8;
DimmRead(AccessAddr); /* Set MRS command. */
PRINT_DEBUG_MEM("Step 18 Address");
PRINT_DEBUG_MEM_HEX32(AccessAddr);
PRINT_DEBUG_MEM("\r");
/* Step 19, 20 */
if (DimmNum == 1) { /* DDR's ODT is 150ohm */
AccessAddr = (u32) CHA_OCD_Default_150ohm;
DimmRead(AccessAddr); /* Issue EMRS OCD Default. */
PRINT_DEBUG_MEM("Step 19 Address ");
PRINT_DEBUG_MEM_HEX32(AccessAddr);
PRINT_DEBUG_MEM("\r");
AccessAddr = (u32) CHA_OCD_Exit_150ohm;
DimmRead(AccessAddr); /* Issue EMRS OCD Calibration Mode Exit. */
PRINT_DEBUG_MEM("Step 20 Address ");
PRINT_DEBUG_MEM_HEX32(AccessAddr);
PRINT_DEBUG_MEM("\r");
} else if (DimmNum == 2) { /* DDR's ODT is 75ohm */
AccessAddr = (u32) CHA_OCD_Default_75ohm;
DimmRead(AccessAddr); /* Issue EMRS OCD Default. */
AccessAddr = (u32) CHA_OCD_Exit_75ohm;
DimmRead(AccessAddr); /* Issue EMRS OCD Calibration Mode Exit. */
} else {
PRINT_DEBUG_MEM("Dimm NUM ERROR: ");
PRINT_DEBUG_MEM_HEX8(DimmNum);
PRINT_DEBUG_MEM("\r");
}
/*
* Step 21. After MRS the device should be ready for full
* functionality within 3 clocks after Tmrd is met.
*/
Data = Reg6BVal;
pci_write_config8(MEMCTRL, 0x6b, Data);
/* Enable bank paging and multi page. */
Data = pci_read_config8(MEMCTRL, 0x69);
Data |= 0x03;
pci_write_config8(MEMCTRL, 0x69, Data);
}
/*===================================================================
Function : InitDDR2_CHB()
Precondition :
Input :
DramAttr: pointer point to DRAM_SYS_ATTR which consist the DDR and Dimm information
in MotherBoard
Output : Void
Purpose : Initialize DDR2 of CHB by standard sequence
Reference :
===================================================================*/
/*// DLL: Enable Reset
static const u32 CHB_MRS_DLL_150[2] = { 0x00020200 | (1 << 20), 0x00000800 }; // with 150 ohm (A17=1, A9=1), (A11=1)(cpu address)
//u32 CHB_MRS_DLL_75[2] = { 0x00020020 | (1 << 20), 0x00000800 }; // with 75 ohm (A17=1, A5=1), (A11=1)(cpu address)
// CPU(DRAM)
// { DLL: Enable. A17(BA0)=1 and A3(MA0)=0 }
// { DLL: reset. A11(MA8)=1 }
//
// DDR2 CL=2 CL=3 CL=4 CL=5 (Burst type=interleave)(WR fine tune in code)
static const u16 CHB_DDR2_MRS_table[4] ={ 0x0150, 0x01D0, 0x0250, 0x02D0 }; // BL=4 ;Use 1X-bandwidth MA table to init DRAM
// MA11 MA10(AP) MA9
#define CHB_MRS_DDR2_TWR2 (0 << 13) + (0 << 20) + (1 << 12) // Value = 001000h
#define CHB_MRS_DDR2_TWR3 (0 << 13) + (1 << 20) + (0 << 12) // Value = 100000h
#define CHB_MRS_DDR2_TWR4 (0 << 13) + (1 << 20) + (1 << 12) // Value = 101000h
#define CHB_MRS_DDR2_TWR5 (1 << 13) + (0 << 20) + (0 << 12) // Value = 002000h
#define CHB_MRS_DDR2_TWR6 (1 << 13) + (0 << 20) + (1 << 12) // Value = 003000h
// DDR2 Twr=2 Twr=3 Twr=4 Twr=5
static const u32 CHB_DDR2_Twr_table[5] = { CHB_MRS_DDR2_TWR2, CHB_MRS_DDR2_TWR3, CHB_MRS_DDR2_TWR4, CHB_MRS_DDR2_TWR5, CHB_MRS_DDR2_TWR6 };
#define CHB_OCD_Exit_150ohm 0x20200 | (1 << 20) // EMRS(1), BA0=1, MA9=MA8=MA7=0,MA6=1,MA2=0 (DRAM bus address)
// A17=1, A12=A11=A10=0,A9=1 ,A5=0 (CPU address)
#define CHB_OCD_Default_150ohm 0x21E00 | (1 << 20) // EMRS(1), BA0=1, MA9=MA8=MA7=1,MA6=1,MA2=0 (DRAM bus address)
// A17=1, A12=A11=A10=1,A9=1 ,A5=0 (CPU address)
//#define CHB_OCD_Exit_75ohm 0x20020 | (1 << 20) // EMRS(1), BA0=1, MA9=MA8=MA7=0,MA6=0,MA2=1 (DRAM bus address)
// A17=1, A12=A11=A10=0,A9=0 ,A5=1 (CPU address)
//#define CHB_OCD_Default_75ohm 0x21C20 | (1 << 20) // EMRS(1), BA0=1, MA9=MA8=MA7=1,MA6=0,MA2=1 (DRAM bus address)
// A17=1, A12=A11=A10=1,A9=0 ,A5=1 (CPU address)
void InitDDR2CHB(
DRAM_SYS_ATTR *DramAttr
)
{
u8 Data;
u8 Idx, CL, BL, Twr;
u32 AccessAddr;
Data = 0x80;
pci_write_config8(MEMCTRL, 0x54, Data);
// step3.
//disable bank paging and multi page
Data=pci_read_config8(MEMCTRL, 0x69);
Data &= ~0x03;
pci_write_config8(MEMCTRL, 0x69, Data);
Data=pci_read_config8(MEMCTRL, 0xd3);
Data |= 0x80;
pci_write_config8(MEMCTRL, 0xd3, Data);
//step 4. Initialize CHB begin
Data=pci_read_config8(MEMCTRL, 0xd3);
Data |= 0x40;
pci_write_config8(MEMCTRL, 0xd3, Data);
//Step 5. NOP command enable
Data=pci_read_config8(MEMCTRL, 0xd7);
Data &= 0xC7;
Data |= 0x08;
pci_write_config8(MEMCTRL, 0xd7, Data);
//Step 6. issue a nop cycle,RegD3[7] 0 -> 1
Data=pci_read_config8(MEMCTRL, 0xd3);
Data &= 0x7F;
pci_write_config8(MEMCTRL, 0xd3, Data);
Data |= 0x80;
pci_write_config8(MEMCTRL, 0xd3, Data);
// Step 7.
// A minimum pause of 200u sec will be provided after the NOP.
// - <<< reduce BOOT UP time >>> -
// Loop 200us
for (Idx = 0; Idx < 0x10; Idx++)
WaitMicroSec(10);
// Step 8.
// all banks precharge command enable
Data=pci_read_config8(MEMCTRL, 0xd7);
Data &= 0xC7;
Data |= 0x10;
pci_write_config8(MEMCTRL, 0xd7, Data);
//step 9. issue a precharge all cycle,RegD3[7] 0 -> 1
Data=pci_read_config8(MEMCTRL, 0xd3);
Data &= 0x7F;
pci_write_config8(MEMCTRL, 0xd3, Data);
Data |= 0x80;
pci_write_config8(MEMCTRL, 0xd3, Data);
//step10. EMRS enable
Data=pci_read_config8(MEMCTRL, 0xd7);
Data &= 0xC7;
Data |= 0x18;
pci_write_config8(MEMCTRL, 0xd7, Data);
Data=pci_read_config8(MEMCTRL, 0xd3);
Data &= 0xC7;
Data |= 0x08;
pci_write_config8(MEMCTRL, 0xd3, Data);
//step11. EMRS DLL Enable and Disable DQS
AccessAddr = CHB_MRS_DLL_150[0] >> 3;
Data =(u8) (AccessAddr & 0xff);
pci_write_config8(MEMCTRL, 0xd9, Data);
Data = (u8)((AccessAddr & 0xff00) >> 8);
pci_write_config8(MEMCTRL, 0xda, Data);
Data=pci_read_config8(MEMCTRL, 0xd7);
Data &= 0xF9;
Data |= (u8)((AccessAddr & 0x30000) >> 15);
pci_write_config8(MEMCTRL, 0xd7, Data);
//step12. issue EMRS cycle
Data=pci_read_config8(MEMCTRL, 0xd3);
Data &= 0x7F;
pci_write_config8(MEMCTRL, 0xd3, Data);
Data |= 0x80;
pci_write_config8(MEMCTRL, 0xd3, Data);
//step13. MSR enable
Data=pci_read_config8(MEMCTRL, 0xd7);
Data &= 0xC7;
Data |= 0x18;
pci_write_config8(MEMCTRL, 0xd7, Data);
Data=pci_read_config8(MEMCTRL, 0xd3);
Data &= 0xC7;
Data |= 0x00;
pci_write_config8(MEMCTRL, 0xd3, Data);
//step 14. MSR DLL Reset
AccessAddr = CHB_MRS_DLL_150[1] >> 3;
Data =(u8) (AccessAddr & 0xff);
pci_write_config8(MEMCTRL, 0xd9, Data);
Data = (u8)((AccessAddr & 0xff00) >> 8);
pci_write_config8(MEMCTRL, 0xda, Data);
Data=pci_read_config8(MEMCTRL, 0xd7);
Data &= 0xF9;
Data |= (u8)((AccessAddr & 0x30000) >> 15);
pci_write_config8(MEMCTRL, 0xd7, Data);
//step15. issue MRS cycle
Data=pci_read_config8(MEMCTRL, 0xd3);
Data &= 0x7F;
pci_write_config8(MEMCTRL, 0xd3, Data);
Data |= 0x80;
pci_write_config8(MEMCTRL, 0xd3, Data);
//clear the address
Data = 0x00;
pci_write_config8(MEMCTRL, 0xda, Data);
//step16. all banks precharge command enable
Data=pci_read_config8(MEMCTRL, 0xd7);
Data &= 0xC7;
Data |= 0x10;
pci_write_config8(MEMCTRL, 0xd7, Data);
// step17. issue precharge all cycle
Data=pci_read_config8(MEMCTRL, 0xd3);
Data &= 0x7F;
pci_write_config8(MEMCTRL, 0xd3, Data);
Data |= 0x80;
pci_write_config8(MEMCTRL, 0xd3, Data);
//step18. CBR cycle enable
Data=pci_read_config8(MEMCTRL, 0xd7);
Data &= 0xC7;
Data |= 0x20;
pci_write_config8(MEMCTRL, 0xd7, Data);
//step 19.20.21
//repeat issue 8 CBR cycle, between each cycle stop 100us
for (Idx = 0; Idx < 8; Idx++)
{
// issue CBR cycle
Data=pci_read_config8(MEMCTRL, 0xd3);
Data &= 0x7F;
pci_write_config8(MEMCTRL, 0xd3, Data);
Data |= 0x80;
pci_write_config8(MEMCTRL, 0xd3, Data);
WaitMicroSec(200);
}
//step22. MSR enable
Data=pci_read_config8(MEMCTRL, 0xd7);
Data &= 0xC7;
Data |= 0x18;
pci_write_config8(MEMCTRL, 0xd7, Data);
Data=pci_read_config8(MEMCTRL, 0xd3);
Data &= 0xC7;
Data |= 0x00;
pci_write_config8(MEMCTRL, 0xd3, Data);
//the SDRAM parameters.(Burst Length, CAS# Latency , Write recovery etc.)
//-------------------------------------------------------------
//Burst Length : really offset Rx6c[1]
Data=pci_read_config8(MEMCTRL, 0x6C);
BL = (Data & 0x02) >> 1;
// CL = really offset RX62[2:0]
Data=pci_read_config8(MEMCTRL, 0x62);
CL = Data & 0x03;
AccessAddr = (u32)(CHB_DDR2_MRS_table[CL]);
if (BL)
{
AccessAddr += 8;
}
//Write recovery : really offset Rx63[7:5]
Data=pci_read_config8(MEMCTRL, 0x63);
Twr = (Data & 0xE0) >> 5;
AccessAddr += CHB_DDR2_Twr_table[Twr];
//MSR Address use addr[20:3]
AccessAddr >>= 3;
//step 23. MSR command
Data = (u8)(AccessAddr & 0xFF);
pci_write_config8(MEMCTRL, 0xD9, Data);
Data = (u8)((AccessAddr & 0xFF00) >> 8);
pci_write_config8(MEMCTRL, 0xda, Data);
Data=pci_read_config8(MEMCTRL, 0xd7);
Data &= 0xF9;
Data |= (u8)(((AccessAddr & 0x30000)>>16) << 1);
pci_write_config8(MEMCTRL, 0xd7, Data);
//step 24. issue MRS cycle
Data=pci_read_config8(MEMCTRL, 0xd3);
Data &= 0x7F;
pci_write_config8(MEMCTRL, 0xd3, Data);
Data |= 0x80;
pci_write_config8(MEMCTRL, 0xd3, Data);
//step 25. EMRS enable
Data=pci_read_config8(MEMCTRL, 0xd7);
Data &= 0xC7;
Data |= 0x18;
pci_write_config8(MEMCTRL, 0xd7, Data);
Data=pci_read_config8(MEMCTRL, 0xd3);
Data &= 0xC7;
Data |= 0x08;
pci_write_config8(MEMCTRL, 0xd3, Data);
//step 26. OCD default
AccessAddr = (CHB_OCD_Default_150ohm) >> 3;
Data =(u8) (AccessAddr & 0xff);
pci_write_config8(MEMCTRL, 0xd9, Data);
Data = (u8)((AccessAddr & 0xff00) >> 8);
pci_write_config8(MEMCTRL, 0xda, Data);
Data=pci_read_config8(MEMCTRL, 0xd7);
Data &= 0xF9;
Data |= (u8)((AccessAddr & 0x30000) >> 15);
pci_write_config8(MEMCTRL, 0xd7, Data);
//step 27. issue EMRS cycle
Data=pci_read_config8(MEMCTRL, 0xd3);
Data &= 0x7F;
pci_write_config8(MEMCTRL, 0xd3, Data);
Data |= 0x80;
pci_write_config8(MEMCTRL, 0xd3, Data);
//step 25. EMRS enable
Data=pci_read_config8(MEMCTRL, 0xd7);
Data &= 0xC7;
Data |= 0x18;
pci_write_config8(MEMCTRL, 0xd7, Data);
Data=pci_read_config8(MEMCTRL, 0xd3);
Data &= 0xC7;
Data |= 0x08;
pci_write_config8(MEMCTRL, 0xd3, Data);
//step 28. OCD Exit
AccessAddr = (CHB_OCD_Exit_150ohm) >> 3;
Data =(u8) (AccessAddr & 0xff);
pci_write_config8(MEMCTRL, 0xd9, Data);
Data = (u8)((AccessAddr & 0xff00) >> 8);
pci_write_config8(MEMCTRL, 0xda, Data);
Data=pci_read_config8(MEMCTRL, 0xd7);
Data &= 0xF9;
Data |= (u8)((AccessAddr & 0x30000) >> 15);
pci_write_config8(MEMCTRL, 0xd7, Data);
//step 29. issue EMRS cycle
Data=pci_read_config8(MEMCTRL, 0xd3);
Data &= 0x7F;
pci_write_config8(MEMCTRL, 0xd3, Data);
Data |= 0x80;
pci_write_config8(MEMCTRL, 0xd3, Data);
//clear all the address
Data = 0x00;
pci_write_config8(MEMCTRL, 0xd9, Data);
Data = 0x00;
pci_write_config8(MEMCTRL, 0xda, Data);
Data=pci_read_config8(MEMCTRL, 0xd7);
Data &= 0xF9;
pci_write_config8(MEMCTRL, 0xd7, Data);
//step 30. normal SDRAM Mode
Data=pci_read_config8(MEMCTRL, 0xd7);
Data &= 0xC7;
Data |= 0x00;
pci_write_config8(MEMCTRL, 0xd7, Data);
Data=pci_read_config8(MEMCTRL, 0xd3);
Data &= 0xC7;
Data |= 0x00;
pci_write_config8(MEMCTRL, 0xd3, Data);
//step 31. exit the initialization mode
Data=pci_read_config8(MEMCTRL, 0xd3);
Data &= 0xBF;
pci_write_config8(MEMCTRL, 0xd3, Data);
//step 32. Enable bank paging and multi page
Data=pci_read_config8(MEMCTRL, 0x69);
Data |= 0x03;
pci_write_config8(MEMCTRL, 0x69, Data);
}
*/
/*===================================================================
Function : InitDDR2CHC()
Precondition :
Input :
DramAttr: pointer point to DRAM_SYS_ATTR which consist the DDR and Dimm information
in MotherBoard
Output : Void
Purpose : Initialize DDR2 of CHC by standard sequence
Reference :
===================================================================*/
// DDR2 CL=2 CL=3 CL=4 CL=5 (Burst type=interleave)(WR fine tune in code)
static const u16 CHC_MRS_table[4] = { 0x22B, 0x23B, 0x24B, 0x25B }; // Use 1X-bandwidth MA table to init DRAM
void InitDDR2CHC(DRAM_SYS_ATTR *DramAttr)
{
u8 Data, Idx, CL, Twr;
u32 AccessAddr;
CB_STATUS Status;
/* Step 3. Clear RxDF[2] to disable Tri-state output. */
Data = pci_read_config8(MEMCTRL, 0xdf);
Data &= 0xFB;
pci_write_config8(MEMCTRL, 0xdf, Data);
/*
* Step 4. Enable the initialization mode of DRAM Controller C with
* NB's PLL clock.
*/
Data = pci_read_config8(MEMCTRL, 0xdb);
Data |= 0x60;
pci_write_config8(MEMCTRL, 0xdb, Data);
/* Step 5. NOP command enable. */
Data = pci_read_config8(MEMCTRL, 0xdb);
Data &= 0xE3;
Data |= 0x00;
pci_write_config8(MEMCTRL, 0xdb, Data);
/* Step 6. Issue a nop cycle, RegDB[1] 0 -> 1. */
Data = pci_read_config8(MEMCTRL, 0xdb);
Data |= 0x2;
pci_write_config8(MEMCTRL, 0xdb, Data);
Data &= 0xFD;
pci_write_config8(MEMCTRL, 0xdb, Data);
/*
* Step 7.
* A minimum pause of 200u sec will be provided after the NOP.
* - <<< reduce BOOT UP time >>> -
* Loop 200us
*/
for (Idx = 0; Idx < 0x10; Idx++)
WaitMicroSec(100);
/* Step 8. Signal bank precharge command enable. */
Data = pci_read_config8(MEMCTRL, 0xdb);
Data &= 0xE3;
Data |= 0x14;
pci_write_config8(MEMCTRL, 0xdb, Data);
/* Set MA10 = 1, precharge all bank. */
Data = 0x00;
pci_write_config8(MEMCTRL, 0xf8, Data);
Data = 0x04;
pci_write_config8(MEMCTRL, 0xf9, Data);
/* step 9. Issue a precharge all cycle, RegD3[7] 0 -> 1. */
Data = pci_read_config8(MEMCTRL, 0xdb);
Data |= 0x2;
pci_write_config8(MEMCTRL, 0xdb, Data);
Data &= 0xFD;
pci_write_config8(MEMCTRL, 0xdb, Data);
/* Step 10. MRS enable. */
Data = pci_read_config8(MEMCTRL, 0xdb);
Data &= 0xE3;
Data |= 0x1C;
pci_write_config8(MEMCTRL, 0xdb, Data);
/* Step 11. EMRS DLL enable and Disable DQS. */
Data = 0x40;
pci_write_config8(MEMCTRL, 0xf8, Data);
Data = 0x24;
pci_write_config8(MEMCTRL, 0xf9, Data);
/* Step 12. Issue EMRS cycle. */
Data = pci_read_config8(MEMCTRL, 0xdb);
Data |= 0x2;
pci_write_config8(MEMCTRL, 0xdb, Data);
Data &= 0xFD;
pci_write_config8(MEMCTRL, 0xdb, Data);
/* Step 13. MSR enable. */
Data = pci_read_config8(MEMCTRL, 0xdb);
Data &= 0xE3;
Data |= 0x1C;
pci_write_config8(MEMCTRL, 0xdb, Data);
/* Step 14. MSR DLL Reset. */
Data = 0x00;
pci_write_config8(MEMCTRL, 0xf8, Data);
Data = 0x01;
pci_write_config8(MEMCTRL, 0xf9, Data);
/* Step 15. Issue MRS cycle. */
Data = pci_read_config8(MEMCTRL, 0xdb);
Data |= 0x2;
pci_write_config8(MEMCTRL, 0xdb, Data);
Data &= 0xFD;
pci_write_config8(MEMCTRL, 0xdb, Data);
/* Step 16. Signal banks precharge command enable. */
Data = pci_read_config8(MEMCTRL, 0xdb);
Data &= 0xE3;
Data |= 0x14;
pci_write_config8(MEMCTRL, 0xdb, Data);
/* Set MA10 = 1, precharge all bank. */
Data = 0x00;
pci_write_config8(MEMCTRL, 0xf8, Data);
Data = 0x04;
pci_write_config8(MEMCTRL, 0xf9, Data);
/* Step 17. Issue precharge all cycle. */
Data = pci_read_config8(MEMCTRL, 0xdb);
Data |= 0x2;
pci_write_config8(MEMCTRL, 0xdb, Data);
Data &= 0xFD;
pci_write_config8(MEMCTRL, 0xdb, Data);
/* Step 18. CBR cycle enable. */
Data = pci_read_config8(MEMCTRL, 0xdb);
Data &= 0xE3;
Data |= 0x18;
pci_write_config8(MEMCTRL, 0xdb, Data);
Data = 0x00;
pci_write_config8(MEMCTRL, 0xf8, Data);
Data = 0x00;
pci_write_config8(MEMCTRL, 0xf9, Data);
//step 19.20.21
//repeat issue 8 CBR cycle, between each cycle stop 100us
for (Idx = 0; Idx < 8; Idx++) {
// issue CBR cycle
Data = pci_read_config8(MEMCTRL, 0xdb);
Data |= 0x2;
pci_write_config8(MEMCTRL, 0xdb, Data);
Data &= 0xFD;
pci_write_config8(MEMCTRL, 0xdb, Data);
WaitMicroSec(100);
}
//the SDRAM parameters.(, CAS# Latency , Write recovery etc.)
//------------------------------------------------------------
// CL = really offset RXDC[7:6]
Data = pci_read_config8(MEMCTRL, 0xdc);
CL = (Data & 0xC0) >> 6;
AccessAddr = (u32) (CHC_MRS_table[CL]);
//Write recovery : really offset Rx63[7:5]
Data = pci_read_config8(MEMCTRL, 0x63);
Twr = (Data & 0xE0) >> 5;
AccessAddr += Twr * 0x200;
//step22. MSR enable
Data = pci_read_config8(MEMCTRL, 0xdb);
Data &= 0xE3;
Data |= 0x1C;
pci_write_config8(MEMCTRL, 0xdb, Data);
//step 23. MSR command
Data = (u8) (AccessAddr & 0xFF);
pci_write_config8(MEMCTRL, 0xf8, Data);
Data = (u8) ((AccessAddr & 0xFF00) >> 8);
pci_write_config8(MEMCTRL, 0xf9, Data);
//step 24. issue MRS cycle
Data = pci_read_config8(MEMCTRL, 0xdb);
Data |= 0x2;
pci_write_config8(MEMCTRL, 0xdb, Data);
Data &= 0xFD;
pci_write_config8(MEMCTRL, 0xdb, Data);
//step 25. EMRS enable
Data = pci_read_config8(MEMCTRL, 0xdb);
Data &= 0xE3;
Data |= 0x1C;
pci_write_config8(MEMCTRL, 0xdb, Data);
//step 26. OCD default
Data = 0xC0;
pci_write_config8(MEMCTRL, 0xf8, Data);
Data = 0x27;
pci_write_config8(MEMCTRL, 0xf9, Data);
//step 27. issue EMRS cycle
Data = pci_read_config8(MEMCTRL, 0xdb);
Data |= 0x2;
pci_write_config8(MEMCTRL, 0xdb, Data);
Data &= 0xFD;
pci_write_config8(MEMCTRL, 0xdb, Data);
//step 28. OCD Exit
Data = 0x40;
pci_write_config8(MEMCTRL, 0xf8, Data);
Data = 0x24;
pci_write_config8(MEMCTRL, 0xf9, Data);
//step 29. issue EMRS cycle
Data = pci_read_config8(MEMCTRL, 0xdb);
Data |= 0x2;
pci_write_config8(MEMCTRL, 0xdb, Data);
Data &= 0xFD;
pci_write_config8(MEMCTRL, 0xdb, Data);
Status = VerifyChc();
if (Status != CB_SUCCESS)
PRINT_DEBUG_MEM("Error!!!!CHC init error!\r");
//step 31. exit the initialization mode
Data = pci_read_config8(MEMCTRL, 0xdb);
Data &= 0x9F;
pci_write_config8(MEMCTRL, 0xdb, Data);
}
CB_STATUS VerifyChc(void)
{
u8 Data, ByteVal, Index, pad;
u16 row;
//first write the pad to all the address
//the row bits is 13 and rank bit is 2, so the address bits is 15 and the value is 0x7fff
//verify each MA[0:12],BA[0:1]
pad = 1;
for (row = 0; row < 0x8000; row++) {
/* Set the write value, Verify each MD[15:0]. */
for (Data = pad, Index = 0; Index < 16; Index++) {
Data <<= 1;
if (Data == 0)
Data = 1;
pci_write_config8(PCI_DEV(0, 0, 7), 0xC0 + Index, Data);
}
/* Issue the bank active command. */
// bank active command enable
Data = pci_read_config8(MEMCTRL, 0xdb);
Data &= 0xE3;
Data |= 0x10;
pci_write_config8(MEMCTRL, 0xdb, Data);
Data = (u8) (row && 0xFF);
pci_write_config8(MEMCTRL, 0xf8, Data);
Data = (u8) ((row && 0xFF) >> 8);
pci_write_config8(MEMCTRL, 0xf9, Data);
/* Issue active cycle. */
Data = pci_read_config8(MEMCTRL, 0xdb);
Data |= 0x2;
pci_write_config8(MEMCTRL, 0xdb, Data);
Data &= 0xFD;
pci_write_config8(MEMCTRL, 0xdb, Data);
/* Issue ready/completion for read/write. */
// read/completion command enable
Data = pci_read_config8(MEMCTRL, 0xdb);
Data &= 0xE3;
Data |= 0x04;
pci_write_config8(MEMCTRL, 0xdb, Data);
Data = 0x00;
pci_write_config8(MEMCTRL, 0xf8, Data);
Data = 0x00;
pci_write_config8(MEMCTRL, 0xf9, Data);
/* Issue read/completion cycle. */
Data = pci_read_config8(MEMCTRL, 0xdb);
Data |= 0x2;
pci_write_config8(MEMCTRL, 0xdb, Data);
Data &= 0xFD;
pci_write_config8(MEMCTRL, 0xdb, Data);
/* Issue write command. */
// write command enable
Data = pci_read_config8(MEMCTRL, 0xdb);
Data &= 0xE3;
Data |= 0x0C;
pci_write_config8(MEMCTRL, 0xdb, Data);
Data = 0x00;
pci_write_config8(MEMCTRL, 0xf8, Data);
Data = (u8) ((row & 0x60) << 5);
pci_write_config8(MEMCTRL, 0xf9, Data);
/* Issue write cycle. */
Data = pci_read_config8(MEMCTRL, 0xdb);
Data |= 0x2;
pci_write_config8(MEMCTRL, 0xdb, Data);
Data &= 0xFD;
pci_write_config8(MEMCTRL, 0xdb, Data);
////issue ready/completion for read/write
// read/completion command enable
Data = pci_read_config8(MEMCTRL, 0xdb);
Data &= 0xE3;
Data |= 0x04;
pci_write_config8(MEMCTRL, 0xdb, Data);
Data = 0x00;
pci_write_config8(MEMCTRL, 0xf8, Data);
Data = 0x00;
pci_write_config8(MEMCTRL, 0xf9, Data);
/* Issue read/completion cycle. */
Data = pci_read_config8(MEMCTRL, 0xdb);
Data |= 0x2;
pci_write_config8(MEMCTRL, 0xdb, Data);
Data &= 0xFD;
pci_write_config8(MEMCTRL, 0xdb, Data);
/* Issue the bank active command. */
// bank active command enable
Data = pci_read_config8(MEMCTRL, 0xdb);
Data &= 0xE3;
Data |= 0x10;
pci_write_config8(MEMCTRL, 0xdb, Data);
Data = (u8) (row && 0xFF);
pci_write_config8(MEMCTRL, 0xf8, Data);
Data = (u8) ((row && 0xFF) >> 8);
pci_write_config8(MEMCTRL, 0xf9, Data);
// issue active cycle
Data = pci_read_config8(MEMCTRL, 0xdb);
Data |= 0x2;
pci_write_config8(MEMCTRL, 0xdb, Data);
Data &= 0xFD;
pci_write_config8(MEMCTRL, 0xdb, Data);
////issue ready/completion for read/write
// read/completion command enable
Data = pci_read_config8(MEMCTRL, 0xdb);
Data &= 0xE3;
Data |= 0x04;
pci_write_config8(MEMCTRL, 0xdb, Data);
Data = 0x00;
pci_write_config8(MEMCTRL, 0xf8, Data);
Data = 0x00;
pci_write_config8(MEMCTRL, 0xf9, Data);
// issue read/completion cycle
Data = pci_read_config8(MEMCTRL, 0xdb);
Data |= 0x2;
pci_write_config8(MEMCTRL, 0xdb, Data);
Data &= 0xFD;
pci_write_config8(MEMCTRL, 0xdb, Data);
////issue read command
// read/completion command enable
Data = pci_read_config8(MEMCTRL, 0xdb);
Data &= 0xE3;
Data |= 0x08;
pci_write_config8(MEMCTRL, 0xdb, Data);
Data = 0x00;
pci_write_config8(MEMCTRL, 0xf8, Data);
Data = (u8) ((row & 0x60) << 5);
pci_write_config8(MEMCTRL, 0xf9, Data);
// issue read cycle
Data = pci_read_config8(MEMCTRL, 0xdb);
Data |= 0x2;
pci_write_config8(MEMCTRL, 0xdb, Data);
Data &= 0xFD;
pci_write_config8(MEMCTRL, 0xdb, Data);
////issue ready/completion for read/write
// read/completion command enable
Data = pci_read_config8(MEMCTRL, 0xdb);
Data &= 0xE3;
Data |= 0x04;
pci_write_config8(MEMCTRL, 0xdb, Data);
Data = 0x00;
pci_write_config8(MEMCTRL, 0xf8, Data);
Data = 0x00;
pci_write_config8(MEMCTRL, 0xf9, Data);
/* Issue read/completion cycle. */
Data = pci_read_config8(MEMCTRL, 0xdb);
Data |= 0x2;
pci_write_config8(MEMCTRL, 0xdb, Data);
Data &= 0xFD;
pci_write_config8(MEMCTRL, 0xdb, Data);
/* Verify the value. */
for (ByteVal = pad, Index = 0; Index < 16; Index++) {
Data = pci_read_config8(PCI_DEV(0, 0, 7), 0xD0 + Index);
if (ByteVal != Data) {
PRINT_DEBUG_MEM("Error! row = %x, index =%x, "
"data = %x, byteval=%x\r");
}
ByteVal <<= 1;
if (ByteVal == 0)
ByteVal = 1;
}
pad <<= 1;
if (pad == 0)
pad = 1;
}
return CB_SUCCESS;
}