summaryrefslogtreecommitdiffstats
path: root/src/northbridge/via/vx800/freq_setting.c
diff options
context:
space:
mode:
authorUwe Hermann <uwe@hermann-uwe.de>2009-05-27 17:06:54 +0000
committerUwe Hermann <uwe@hermann-uwe.de>2009-05-27 17:06:54 +0000
commit5c044c732fc28b09eb58956a85b141af194f2b94 (patch)
treefde799f7c44df7b06e0ad0f98b06fb54571c265a /src/northbridge/via/vx800/freq_setting.c
parentf2a4e63f926a59759309d93e1af60e3c3f7d5c13 (diff)
downloadcoreboot-5c044c732fc28b09eb58956a85b141af194f2b94.tar.gz
coreboot-5c044c732fc28b09eb58956a85b141af194f2b94.tar.bz2
coreboot-5c044c732fc28b09eb58956a85b141af194f2b94.zip
Make directory hierarchy flat to match the same layout we use
for other chipsets, as suggested on IRC. Signed-off-by: Uwe Hermann <uwe@hermann-uwe.de> Acked-by: Uwe Hermann <uwe@hermann-uwe.de> git-svn-id: svn://svn.coreboot.org/coreboot/trunk@4317 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
Diffstat (limited to 'src/northbridge/via/vx800/freq_setting.c')
-rw-r--r--src/northbridge/via/vx800/freq_setting.c235
1 files changed, 235 insertions, 0 deletions
diff --git a/src/northbridge/via/vx800/freq_setting.c b/src/northbridge/via/vx800/freq_setting.c
new file mode 100644
index 000000000000..ed4184ec7773
--- /dev/null
+++ b/src/northbridge/via/vx800/freq_setting.c
@@ -0,0 +1,235 @@
+/*
+ * 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 CalcCLAndFreq(DRAM_SYS_ATTR * DramAttr);
+
+/*
+ Set DRAM Frequency
+*/
+void DRAMFreqSetting(DRAM_SYS_ATTR * DramAttr)
+{
+
+ u8 Data = 0;
+
+ PRINT_DEBUG_MEM("Dram Frequency setting \r");
+
+ //calculate dram frequency using SPD data
+ CalcCLAndFreq(DramAttr);
+
+ //init some Dramc control by Simon Chu slide
+ //Must use "CPU delay" to make sure VLINK is dis-connect
+ Data = pci_read_config8(PCI_DEV(0, 0, 7), 0x47);
+ Data = (u8) (Data | 0x04);
+ pci_write_config8(PCI_DEV(0, 0, 7), 0x47, Data);
+
+ //in order to make sure NB command buffer don`t have pending request(C2P cycle)
+ //CPU DELAY
+ WaitMicroSec(20);
+
+ //Before Set Dram Frequency, we must set 111 by Simon Chu slide.
+ Data = pci_read_config8(MEMCTRL, 0x90);
+ Data = (u8) ((Data & 0xf8) | 7);
+ pci_write_config8(MEMCTRL, 0x90, Data);
+
+ WaitMicroSec(20);
+
+ //Set Dram Frequency.
+ Data = pci_read_config8(MEMCTRL, 0x90);
+ switch (DramAttr->DramFreq) {
+ case DIMMFREQ_400:
+ Data = (u8) ((Data & 0xf8) | 3);
+ break;
+ case DIMMFREQ_533:
+ Data = (u8) ((Data & 0xf8) | 4);
+ break;
+ case DIMMFREQ_667:
+ Data = (u8) ((Data & 0xf8) | 5);
+ break;
+ case DIMMFREQ_800:
+ Data = (u8) ((Data & 0xf8) | 6);
+ break;
+ default:
+ Data = (u8) ((Data & 0xf8) | 1);;
+ }
+ pci_write_config8(MEMCTRL, 0x90, Data);
+
+ //CPU Delay
+ WaitMicroSec(20);
+
+ // Manual reset and adjust DLL when DRAM change frequency
+ Data = pci_read_config8(MEMCTRL, 0x6B);
+ Data = (u8) ((Data & 0x2f) | 0xC0);
+ pci_write_config8(MEMCTRL, 0x6B, Data);
+
+ //CPU Delay
+ WaitMicroSec(20);
+
+ Data = pci_read_config8(MEMCTRL, 0x6B);
+ Data = (u8) (Data | 0x10);
+ pci_write_config8(MEMCTRL, 0x6B, Data);
+
+ //CPU Delay
+ WaitMicroSec(20);
+
+ Data = pci_read_config8(MEMCTRL, 0x6B);
+ Data = (u8) (Data & 0x3f);
+ pci_write_config8(MEMCTRL, 0x6B, Data);
+
+ //disable V_LINK Auto-Disconnect, or else program may stopped at some place and
+ //we cannot find the reason
+ Data = pci_read_config8(PCI_DEV(0, 0, 7), 0x47);
+ Data = (u8) (Data & 0xFB);
+ pci_write_config8(PCI_DEV(0, 0, 7), 0x47, Data);
+
+}
+
+
+/*
+ calculate CL and dram freq
+ DDR1
+ +---+---+---+---+---+---+---+---+
+ | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+ +---+---+---+---+---+---+---+---+
+ |TBD| 4 |3.5| 3 |2.5| 2 |1.5| 1 |
+ +---+---+---+---+---+---+---+---+
+ DDR2
+ +---+---+---+---+---+---+---+---+
+ | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+ +---+---+---+---+---+---+---+---+
+ |TBD| 6 | 5 | 4 | 3 | 2 |TBD|TBD|
+ +---+---+---+---+---+---+---+---+
+*/
+static const u8 CL_DDR1[7] = { 10, 15, 20, 25, 30, 35, 40 };
+static const u8 CL_DDR2[7] = { 0, 0, 20, 30, 40, 50, 60 };
+
+void CalcCLAndFreq(DRAM_SYS_ATTR * DramAttr)
+{
+ u8 AllDimmSupportedCL, Tmp;
+ u8 CLMask, tmpMask, IndexDelta;
+ u8 SckId, BitId, TmpId;
+ u16 CycTime, TmpCycTime;
+
+ /*1.list the CL value that all DIMM supported */
+ AllDimmSupportedCL = 0xFF;
+ if (RAMTYPE_SDRAMDDR2 == DramAttr->DramType)
+ AllDimmSupportedCL &= 0x7C; /*bit2,3,4,5,6 */
+ else /*DDR1 */
+ AllDimmSupportedCL &= 0x7F; /*bit0,1,2,3,4,5,6 */
+ for (SckId = 0; SckId < MAX_SOCKETS; SckId++) {
+ if (DramAttr->DimmInfo[SckId].bPresence) { /*all DIMM supported CL */
+ AllDimmSupportedCL &=
+ (DramAttr->DimmInfo[SckId].
+ SPDDataBuf[SPD_SDRAM_CAS_LATENCY]);
+ }
+ }
+ if (!AllDimmSupportedCL) { /*if equal 0, no supported CL */
+ PRINT_DEBUG_MEM("SPD Data Error, Can not get CL !!!! \r");
+ for (;;);
+ }
+
+ /*Get CL Value */
+ CLMask = 0x40; /*from Bit6 */
+
+ for (BitId = 7; BitId > 0; BitId--) {
+ if ((AllDimmSupportedCL & CLMask) == CLMask) { /*find the first bit */
+ if (RAMTYPE_SDRAMDDR2 == DramAttr->DramType)
+ DramAttr->CL = CL_DDR2[BitId - 1];
+ else /*DDR1 */
+ DramAttr->CL = CL_DDR1[BitId - 1];
+ break;
+ }
+ CLMask >>= 1;
+ }
+
+ /*according the CL value calculate the cycle time, for X or X-1 or X-2 */
+ CycTime = 0;
+ TmpCycTime = 0;
+
+ for (SckId = 0; SckId < MAX_SOCKETS; SckId++) {
+ if (DramAttr->DimmInfo[SckId].bPresence) {
+ Tmp =
+ (DramAttr->DimmInfo[SckId].
+ SPDDataBuf[SPD_SDRAM_CAS_LATENCY]);
+ tmpMask = 0x40;
+ for (TmpId = 7; TmpId > 0; TmpId--) {
+ if ((Tmp & tmpMask) == tmpMask)
+ break;
+ tmpMask >>= 1;
+ }
+ if (TmpId - BitId == 0) { /*get Cycle time for X, SPD BYTE9 */
+ TmpCycTime =
+ DramAttr->DimmInfo[SckId].
+ SPDDataBuf[SPD_SDRAM_TCLK_X];
+ } else if (TmpId - BitId == 1) { /*get Cycle time for X-1, SPD BYTE23 */
+ TmpCycTime =
+ DramAttr->DimmInfo[SckId].
+ SPDDataBuf[SPD_SDRAM_TCLK_X_1];
+ } else if (TmpId - BitId == 2) { /*get cycle time for X-2, SPD BYTE25 */
+ TmpCycTime =
+ DramAttr->DimmInfo[SckId].
+ SPDDataBuf[SPD_SDRAM_TCLK_X_2];
+ } else {
+ //error!!!
+ }
+ if (TmpCycTime > CycTime) /*get the most cycle time,there is some problem! */
+ CycTime = TmpCycTime;
+ }
+ }
+
+ if (CycTime <= 0) {
+ //error!
+ for (;;);
+ }
+
+ /* cycle time value
+ 0x25-->2.5ns Freq=400 DDR800
+ 0x30-->3.0ns Freq=333 DDR667
+ 0x3D-->3.75ns Freq=266 DDR533
+ 0x50-->5.0ns Freq=200 DDR400
+ 0x60-->6.0ns Freq=166 DDR333
+ 0x75-->7.5ns Freq=133 DDR266
+ 0xA0-->10.0ns Freq=100 DDR200
+ */
+ if (CycTime <= 0x25) {
+ DramAttr->DramFreq = DIMMFREQ_800;
+ DramAttr->DramCyc = 250;
+ } else if (CycTime <= 0x30) {
+ DramAttr->DramFreq = DIMMFREQ_667;
+ DramAttr->DramCyc = 300;
+ } else if (CycTime <= 0x3d) {
+ DramAttr->DramFreq = DIMMFREQ_533;
+ DramAttr->DramCyc = 375;
+ } else if (CycTime <= 0x50) {
+ DramAttr->DramFreq = DIMMFREQ_400;
+ DramAttr->DramCyc = 500;
+ } else if (CycTime <= 0x60) {
+ DramAttr->DramFreq = DIMMFREQ_333;
+ DramAttr->DramCyc = 600;
+ } else if (CycTime <= 0x75) {
+ DramAttr->DramFreq = DIMMFREQ_266;
+ DramAttr->DramCyc = 750;
+ } else if (CycTime <= 0xA0) {
+ DramAttr->DramFreq = DIMMFREQ_200;
+ DramAttr->DramCyc = 1000;
+ }
+ //if set the frequence mannul
+ PRINT_DEBUG_MEM("Dram Frequency:");
+ PRINT_DEBUG_MEM_HEX16(DramAttr->DramFreq);
+ PRINT_DEBUG_MEM(" \r");
+}