summaryrefslogtreecommitdiff
path: root/src/northbridge/via/vx800/clk_ctrl.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/northbridge/via/vx800/clk_ctrl.c')
-rw-r--r--src/northbridge/via/vx800/clk_ctrl.c312
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);
+
+}