diff options
Diffstat (limited to 'src/northbridge/via/vx800/clk_ctrl.c')
-rw-r--r-- | src/northbridge/via/vx800/clk_ctrl.c | 312 |
1 files changed, 312 insertions, 0 deletions
diff --git a/src/northbridge/via/vx800/clk_ctrl.c b/src/northbridge/via/vx800/clk_ctrl.c new file mode 100644 index 0000000000..13edc1f996 --- /dev/null +++ b/src/northbridge/via/vx800/clk_ctrl.c @@ -0,0 +1,312 @@ +/* + * 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 DutyCycleCtrl(DRAM_SYS_ATTR * DramAttr) +{ + u8 Data; + u8 FreqId; + u8 i; + + if (DIMMFREQ_800 == DramAttr->DramFreq) + FreqId = 2; + else if (DIMMFREQ_667 == DramAttr->DramFreq) + FreqId = 3; + else if (DIMMFREQ_533 == DramAttr->DramFreq) + FreqId = 4; + else if (DIMMFREQ_400 == DramAttr->DramFreq) + FreqId = 5; + else + FreqId = 5; + + if (DramAttr->RankNumChA > 0) { // 1 rank + for (i = 0; i < DUTY_CYCLE_REG_NUM; i++) { + Data = + pci_read_config8(MEMCTRL, + ChA_Duty_Control_DDR2[i][0]); + Data &= ChA_Duty_Control_DDR2[i][1]; /*Mask */ + Data |= ChA_Duty_Control_DDR2[i][FreqId]; /*set Value */ + pci_write_config8(MEMCTRL, + ChA_Duty_Control_DDR2[i][0], + Data); + } + } + if (1 == ENABLE_CHC) { // 1 rank + for (i = 0; i < DUTY_CYCLE_REG_NUM; i++) { + Data = + pci_read_config8(MEMCTRL, + ChB_Duty_Control_DDR2[i][0]); + Data &= ChB_Duty_Control_DDR2[i][1]; /*Mask */ + Data |= ChB_Duty_Control_DDR2[i][FreqId]; /*set Value */ + pci_write_config8(MEMCTRL, + ChB_Duty_Control_DDR2[i][0], + Data); + } + } + +} + +/* +DRAM clock phase and delay control +*/ +//sub routine list +void ClkPhsCtrlFBMDDR2(DRAM_SYS_ATTR * DramAttr); + +void WrtDataPhsCtrl(DRAM_SYS_ATTR * DramAttr); + +void DQDQSOutputDlyCtrl(DRAM_SYS_ATTR * DramAttr); + +void DQSInputCaptureCtrl(DRAM_SYS_ATTR * DramAttr); + +void DCLKPhsCtrl(DRAM_SYS_ATTR * DramAttr); + + +void DRAMClkCtrl(DRAM_SYS_ATTR * DramAttr) +{ + /*write data clock phase control */ + WrtDataPhsCtrl(DramAttr); + /*clock phase control */ + ClkPhsCtrlFBMDDR2(DramAttr); + /**/ DQDQSOutputDlyCtrl(DramAttr); + /**/ DQSInputCaptureCtrl(DramAttr); + DCLKPhsCtrl(DramAttr); +} + +void ClkPhsCtrlFBMDDR2(DRAM_SYS_ATTR * DramAttr) +{ + u8 Data; + + u8 FreqId, i; + + if (DramAttr->DramFreq == DIMMFREQ_800) + FreqId = 2; + else if (DramAttr->DramFreq == DIMMFREQ_667) + FreqId = 3; + else if (DramAttr->DramFreq == DIMMFREQ_533) + FreqId = 4; + else if (DramAttr->DramFreq == DIMMFREQ_400) + FreqId = 5; + else + FreqId = 5; + /*channel A */// 2~4 Rank + if (DramAttr->RankNumChA == 1) { // 1 rank + for (i = 0; i < 3; i++) { + Data = + pci_read_config8(MEMCTRL, + DDR2_ChA_Clk_Phase_Table_1R[i] + [0]); + Data &= DDR2_ChA_Clk_Phase_Table_1R[i][1]; /*Mask */ + Data |= DDR2_ChA_Clk_Phase_Table_1R[i][FreqId]; /*set Value */ + pci_write_config8(MEMCTRL, + DDR2_ChA_Clk_Phase_Table_1R[i] + [0], Data); + } + } else if (DramAttr->RankNumChA > 1) { // 2~4 Rank + for (i = 0; i < 3; i++) { + Data = + pci_read_config8(MEMCTRL, + DDR2_ChA_Clk_Phase_Table_2R[i] + [0]); + Data &= DDR2_ChA_Clk_Phase_Table_2R[i][1]; /*Mask */ + Data |= DDR2_ChA_Clk_Phase_Table_2R[i][FreqId]; /*set Value */ + pci_write_config8(MEMCTRL, + DDR2_ChA_Clk_Phase_Table_2R[i] + [0], Data); + } + } +#if ENABLE_CHB + if (DramAttr->RankNumChB > 0) { // 1 rank + for (i = 0; i < 3; i++) { + Data = + pci_read_config8(MEMCTRL, + DDR2_ChB_Clk_Phase_Table_1R[i] + [0]); + Data &= DDR2_ChB_Clk_Phase_Table_1R[i][1]; /*Mask */ + Data |= DDR2_ChB_Clk_Phase_Table_1R[i][FreqId]; /*set Value */ + pci_write_config8(MEMCTRL, + DDR2_ChB_Clk_Phase_Table_1R[i] + [0], Data); + } + } +#endif +} + +void WrtDataPhsCtrl(DRAM_SYS_ATTR * DramAttr) +{ + u8 Data; + u8 FreqId, i; + + + if (DIMMFREQ_800 == DramAttr->DramFreq) + FreqId = 2; + else if (DIMMFREQ_667 == DramAttr->DramFreq) + FreqId = 3; + else if (DIMMFREQ_533 == DramAttr->DramFreq) + FreqId = 4; + else if (DIMMFREQ_400 == DramAttr->DramFreq) + FreqId = 5; + else + FreqId = 5; + + if (DramAttr->RankNumChA > 0) { // 1 rank + for (i = 0; i < WrtData_REG_NUM; i++) { + Data = + pci_read_config8(MEMCTRL, + DDR2_ChA_WrtData_Phase_Table + [i][0]); + Data &= DDR2_ChA_WrtData_Phase_Table[i][1]; /*Mask */ + Data |= DDR2_ChA_WrtData_Phase_Table[i][FreqId]; /*set Value */ + pci_write_config8(MEMCTRL, + DDR2_ChA_WrtData_Phase_Table[i] + [0], Data); + } + } +#if ENABLE_CHB + if (DramAttr->RankNumChB > 0) { // 1 rank + for (i = 0; i < WrtData_REG_NUM; i++) { + Data = + pci_read_config8(MEMCTRL, + DDR2_ChB_WrtData_Phase_Table + [i][0]); + Data &= DDR2_ChB_WrtData_Phase_Table[i][1]; /*Mask */ + Data |= DDR2_ChB_WrtData_Phase_Table[i][FreqId]; /*set Value */ + pci_write_config8(MEMCTRL, + DDR2_ChB_WrtData_Phase_Table[i] + [0], Data); + } + } +#endif + Data = pci_read_config8(MEMCTRL, 0x8C); + Data &= 0xFC; + Data |= 0x03; + pci_write_config8(MEMCTRL, 0x8C, Data); +} + +void DQDQSOutputDlyCtrl(DRAM_SYS_ATTR * DramAttr) +{ + u8 Data; + u8 FreqId; + + if (DIMMFREQ_400 == DramAttr->DramFreq) + FreqId = 0; + else if (DIMMFREQ_533 == DramAttr->DramFreq) + FreqId = 1; + else if (DIMMFREQ_667 == DramAttr->DramFreq) + FreqId = 2; + else if (DIMMFREQ_800 == DramAttr->DramFreq) + FreqId = 2; + else + FreqId = 0; + if (DramAttr->RankNumChA > 0) { + Data = DDR2_CHA_DQ_DQS_Delay_Table[FreqId][0]; + pci_write_config8(MEMCTRL, 0xf0, Data); + + Data = DDR2_CHA_DQ_DQS_Delay_Table[FreqId][1]; + pci_write_config8(MEMCTRL, 0xf1, Data); + + Data = DDR2_CHA_DQ_DQS_Delay_Table[FreqId][2]; + pci_write_config8(MEMCTRL, 0xf2, Data); + + Data = DDR2_CHA_DQ_DQS_Delay_Table[FreqId][3]; + pci_write_config8(MEMCTRL, 0xf3, Data); + } +#if ENABLE_CHB + if (DramAttr->RankNumChB > 0) { + Data = DDR2_CHB_DQ_DQS_Delay_Table[FreqId][0]; + pci_write_config8(MEMCTRL, 0xf4, Data); + + Data = DDR2_CHB_DQ_DQS_Delay_Table[FreqId][1]; + pci_write_config8(MEMCTRL, 0xf5, Data); + + Data = DDR2_CHB_DQ_DQS_Delay_Table[FreqId][2]; + pci_write_config8(MEMCTRL, 0xf6, Data); + + Data = DDR2_CHB_DQ_DQS_Delay_Table[FreqId][3]; + pci_write_config8(MEMCTRL, 0xf7, Data); + } +#endif +} + +void DQSInputCaptureCtrl(DRAM_SYS_ATTR * DramAttr) +{ + u8 Data; + u8 FreqId, i; + + if (DIMMFREQ_800 == DramAttr->DramFreq) + FreqId = 2; + else if (DIMMFREQ_667 == DramAttr->DramFreq) + FreqId = 3; + else if (DIMMFREQ_533 == DramAttr->DramFreq) + FreqId = 4; + else if (DIMMFREQ_400 == DramAttr->DramFreq) + FreqId = 5; + else + FreqId = 2; + + Data = 0x8A; + pci_write_config8(MEMCTRL, 0x77, Data); + + if (DramAttr->RankNumChA > 0) { // 1 rank + for (i = 0; i < DQS_INPUT_CAPTURE_REG_NUM; i++) { + Data = + pci_read_config8(MEMCTRL, + DDR2_ChA_DQS_Input_Capture_Tbl + [i][0]); + Data &= DDR2_ChA_DQS_Input_Capture_Tbl[i][1]; /*Mask */ + Data |= DDR2_ChA_DQS_Input_Capture_Tbl[i][FreqId]; /*set Value */ + pci_write_config8(MEMCTRL, + DDR2_ChA_DQS_Input_Capture_Tbl[i] + [0], Data); + } + } +#if ENABLE_CHB + if (DramAttr->RankNumChB > 0) { // 1 rank + for (i = 0; i < DQS_INPUT_CAPTURE_REG_NUM; i++) { + Data = + pci_read_config8(MEMCTRL, + DDR2_ChB_DQS_Input_Capture_Tbl + [i][0]); + Data &= DDR2_ChB_DQS_Input_Capture_Tbl[i][1]; /*Mask */ + Data |= DDR2_ChB_DQS_Input_Capture_Tbl[i][FreqId]; /*set Value */ + pci_write_config8(MEMCTRL, + DDR2_ChB_DQS_Input_Capture_Tbl[i] + [0], Data); + } + } +#endif +} + +//This is very important, if you don't set it correctly, dram will be unreliable +//set DCLK Phase control(Reg99H[6:1]) according the DDRII in the dimm +void DCLKPhsCtrl(DRAM_SYS_ATTR * DramAttr) +{ + u8 Data; + + Data = 0; + Data = pci_read_config8(MEMCTRL, 0x99); + Data &= 0xE1; + //DDR in Dimm1, MCLKOA[4,3,0] will output MCLK + if (DramAttr->RankPresentMap & 0x03) + Data |= 0x09 << 1; + //DDR in Dimm2, MCLKOA[5,2,1] will output MCLK + if (DramAttr->RankPresentMap & 0x0C) + Data |= 0x06 << 1; + + pci_write_config8(MEMCTRL, 0x99, Data); + +} |