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