summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBari Ari <bari@onelabs.com>2009-05-27 13:12:42 +0000
committerUwe Hermann <uwe@hermann-uwe.de>2009-05-27 13:12:42 +0000
commit612163e3833e807caeed8889dae41d24026241e7 (patch)
treee0a711474dd3f82eaf43954dc6074ce6857d9be7
parente6e899dde951823ebc9abf997a6af06debac82a3 (diff)
Here's the VIA vx800 patch from OLPC.
It's untested, but a good starting point for everyone. Signed-off-by: Bari Ari <bari@onelabs.com> Acked-by: Ronald G. Minnich <rminnich@gmail.com> Acked-by: Uwe Hermann <uwe@hermann-uwe.de> git-svn-id: svn://svn.coreboot.org/coreboot/trunk@4313 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
-rw-r--r--src/northbridge/via/vx800/Config.lb25
-rw-r--r--src/northbridge/via/vx800/DrivingClkPhaseData.h70
-rw-r--r--src/northbridge/via/vx800/chip.h24
-rw-r--r--src/northbridge/via/vx800/ddr2init/DramInit.c86
-rw-r--r--src/northbridge/via/vx800/ddr2init/DramInit.h263
-rw-r--r--src/northbridge/via/vx800/ddr2init/DramUtil.c249
-rw-r--r--src/northbridge/via/vx800/ddr2init/DramUtil.h47
-rw-r--r--src/northbridge/via/vx800/ddr2init/Translatorddr2init.c34
-rw-r--r--src/northbridge/via/vx800/ddr2init/vx800/ClkCtrl.c312
-rw-r--r--src/northbridge/via/vx800/ddr2init/vx800/DQSSearch.c98
-rw-r--r--src/northbridge/via/vx800/ddr2init/vx800/DRDY_BL.c600
-rw-r--r--src/northbridge/via/vx800/ddr2init/vx800/Detection.c192
-rw-r--r--src/northbridge/via/vx800/ddr2init/vx800/DevInit.c1318
-rw-r--r--src/northbridge/via/vx800/ddr2init/vx800/DrivingSetting.c396
-rw-r--r--src/northbridge/via/vx800/ddr2init/vx800/FinalSetting.c129
-rw-r--r--src/northbridge/via/vx800/ddr2init/vx800/FreqSetting.c235
-rw-r--r--src/northbridge/via/vx800/ddr2init/vx800/RankMap.c363
-rw-r--r--src/northbridge/via/vx800/ddr2init/vx800/TimingSetting.c492
-rw-r--r--src/northbridge/via/vx800/ddr2init/vx800/UMARamSetting.c445
-rw-r--r--src/northbridge/via/vx800/examples/DrivingClkPhaseData.c242
-rw-r--r--src/northbridge/via/vx800/examples/cache_as_ram_auto.c660
-rw-r--r--src/northbridge/via/vx800/examples/chipset_init.c1298
-rw-r--r--src/northbridge/via/vx800/northbridge.c247
-rw-r--r--src/northbridge/via/vx800/northbridge.h25
-rw-r--r--src/northbridge/via/vx800/raminit.c74
-rw-r--r--src/northbridge/via/vx800/raminit.h24
-rw-r--r--src/northbridge/via/vx800/romstrap.inc51
-rw-r--r--src/northbridge/via/vx800/romstrap.lds26
-rw-r--r--src/northbridge/via/vx800/vga.c148
-rw-r--r--src/northbridge/via/vx800/vgabios.c862
-rw-r--r--src/northbridge/via/vx800/vgachip.h34
-rw-r--r--src/northbridge/via/vx800/vx800.h125
-rw-r--r--src/northbridge/via/vx800/vx800_early_serial.c110
-rw-r--r--src/northbridge/via/vx800/vx800_early_smbus.c321
-rw-r--r--src/northbridge/via/vx800/vx800_ide.c204
-rw-r--r--src/northbridge/via/vx800/vx800_lpc.c384
36 files changed, 10213 insertions, 0 deletions
diff --git a/src/northbridge/via/vx800/Config.lb b/src/northbridge/via/vx800/Config.lb
new file mode 100644
index 0000000000..9e6fcfef17
--- /dev/null
+++ b/src/northbridge/via/vx800/Config.lb
@@ -0,0 +1,25 @@
+##
+## 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
+##
+
+config chip.h
+object vgabios.o
+driver northbridge.o
+driver vga.o
+driver vx800_lpc.o
+driver vx800_ide.o
diff --git a/src/northbridge/via/vx800/DrivingClkPhaseData.h b/src/northbridge/via/vx800/DrivingClkPhaseData.h
new file mode 100644
index 0000000000..f6c8feace8
--- /dev/null
+++ b/src/northbridge/via/vx800/DrivingClkPhaseData.h
@@ -0,0 +1,70 @@
+/*
+ * 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
+ */
+
+#ifndef DRIVINGCLKPHASEDATA_H
+#define DRIVINGCLKPHASEDATA_H
+
+//extern u8 DDR2_DQSA_Driving_Table[4] ;
+//extern u8 DDR2_DQSB_Driving_Table[2] ;
+
+//extern u8 DDR2_DQA_Driving_Table[4] ;
+//extern u8 DDR2_DQB_Driving_Table[2] ;
+
+//extern u8 DDR2_CSA_Driving_Table_x8[4] ;
+//extern u8 DDR2_CSB_Driving_Table_x8[2] ;
+//extern u8 DDR2_CSA_Driving_Table_x16[4];
+//extern u8 DDR2_CSB_Driving_Table_x16[2];
+
+#define MA_Table 3
+//extern u8 DDR2_MAA_Driving_Table[MA_Table][4];
+//extern u8 DDR2_MAB_Driving_Table[MA_Table][2];
+
+//extern u8 DDR2_DCLKA_Driving_Table[4] ;
+//extern u8 DDR2_DCLKB_Driving_Table[4];
+
+#define DUTY_CYCLE_FREQ_NUM 6
+#define DUTY_CYCLE_REG_NUM 3
+//extern u8 ChA_Duty_Control_DDR2[DUTY_CYCLE_REG_NUM][DUTY_CYCLE_FREQ_NUM];
+//extern u8 ChB_Duty_Control_DDR2[DUTY_CYCLE_REG_NUM][DUTY_CYCLE_FREQ_NUM];
+
+#define Clk_Phase_Table_DDR2_Width 6
+//extern u8 DDR2_ChA_Clk_Phase_Table_1R[3][Clk_Phase_Table_DDR2_Width];
+//extern u8 DDR2_ChB_Clk_Phase_Table_1R[3][Clk_Phase_Table_DDR2_Width];
+//extern u8 DDR2_ChA_Clk_Phase_Table_2R[3][Clk_Phase_Table_DDR2_Width];
+
+#define WrtData_REG_NUM 4
+#define WrtData_FREQ_NUM 6
+//extern u8 DDR2_ChA_WrtData_Phase_Table[WrtData_REG_NUM ][WrtData_FREQ_NUM];
+//extern u8 DDR2_ChB_WrtData_Phase_Table[WrtData_REG_NUM ][WrtData_FREQ_NUM];
+
+#define DQ_DQS_Delay_Table_Width 4
+//extern u8 DDR2_CHA_DQ_DQS_Delay_Table[4][DQ_DQS_Delay_Table_Width];
+//extern u8 DDR2_CHB_DQ_DQS_Delay_Table[4][DQ_DQS_Delay_Table_Width];
+
+#define DQS_INPUT_CAPTURE_REG_NUM 3
+#define DQS_INPUT_CAPTURE_FREQ_NUM 6
+//extern u8 DDR2_ChA_DQS_Input_Capture_Tbl[DQS_INPUT_CAPTURE_REG_NUM ][DQS_INPUT_CAPTURE_FREQ_NUM];
+//extern u8 DDR2_ChB_DQS_Input_Capture_Tbl[DQS_INPUT_CAPTURE_REG_NUM ][DQS_INPUT_CAPTURE_FREQ_NUM];
+
+//extern u8 Fixed_DQSA_1_2_Rank_Table[4][2];
+//extern u8 Fixed_DQSA_3_4_Rank_Table[4][2];
+
+//extern u8 Fixed_DQSB_1_2_Rank_Table[4][2];
+//extern u8 Fixed_DQSB_3_4_Rank_Table[4][2];
+#endif /* DRIVINGCLKPHASEDATA_H */
diff --git a/src/northbridge/via/vx800/chip.h b/src/northbridge/via/vx800/chip.h
new file mode 100644
index 0000000000..700a398d5c
--- /dev/null
+++ b/src/northbridge/via/vx800/chip.h
@@ -0,0 +1,24 @@
+/*
+ * 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
+ */
+
+struct northbridge_via_vx800_config
+{
+};
+
+extern struct chip_operations northbridge_via_vx800_ops;
diff --git a/src/northbridge/via/vx800/ddr2init/DramInit.c b/src/northbridge/via/vx800/ddr2init/DramInit.c
new file mode 100644
index 0000000000..ad4d721cbd
--- /dev/null
+++ b/src/northbridge/via/vx800/ddr2init/DramInit.c
@@ -0,0 +1,86 @@
+/*
+ * 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; either 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
+ */
+
+#include "lib/memset.c"
+CB_STATUS DDR2_DRAM_INIT()
+{
+ CB_STATUS Status;
+ u8 i;
+ u32 RamSize;
+ BOOLEAN bTest;
+ DRAM_SYS_ATTR DramAttr;
+
+ PRINT_DEBUG_MEM("DRAM_INIT \r");
+
+ memset(&DramAttr, 0, sizeof(DRAM_SYS_ATTR));
+ /*Step1 DRAM Detection; DDR1 or DDR2; Get SPD Data; Rank Presence;64 or 128bit; Unbuffered or registered; 1T or 2T */
+ DRAMDetect(&DramAttr);
+
+ //Step2 set Frequency; calculate CL and Frequncy from SPD data; set the Frequency
+ DRAMFreqSetting(&DramAttr);
+ //Step3 Set DRAM Timing; CL, tRP, tRCD, tRAS, tRFC, tRRD, tWR, tWTR, tRTP
+ DRAMTimingSetting(&DramAttr);
+ //Step4 DRDY
+ DRAMDRDYSetting(&DramAttr);
+ //Step5 Burst length
+ DRAMBurstLength(&DramAttr);
+ //Step6 DRAM Driving Adjustment
+ DRAMDriving(&DramAttr);
+ //Step7 duty cycle control
+ DutyCycleCtrl(&DramAttr);
+ //Step8 DRAM clock phase and delay control
+ DRAMClkCtrl(&DramAttr);
+ //Step9 set register before init DRAM device
+ DRAMRegInitValue(&DramAttr);
+ //Step10 DDR and DDR2 initialize process
+ DRAMInitializeProc(&DramAttr);
+
+ //Step13 Interleave function in rankmap.c
+ DRAMBankInterleave(&DramAttr);
+ //Step14 Sizing
+ DRAMSizingMATypeM(&DramAttr);
+
+ //Step11 Search DQS and DQ output delay
+ DRAMDQSOutputSearch(&DramAttr);
+ //Step12 Search DQS input delay
+ DRAMDQSInputSearch(&DramAttr);
+
+ //Step15 DDR fresh counter setting
+ DRAMRefreshCounter(&DramAttr);
+ //Step16 Final register setting for improve performance
+ DRAMRegFinalValue(&DramAttr);
+
+ RamSize = 0;
+ for (i = 0; i < MAX_RANKS; i++) {
+ if (DramAttr.RankSize[i] == 0) {
+ continue;
+ }
+ RamSize += DramAttr.RankSize[i];
+ }
+ PRINT_DEBUG_MEM("RamSize=");
+ PRINT_DEBUG_MEM_HEX32(RamSize);
+ PRINT_DEBUG_MEM("\r");
+ DumpRegisters(0, 3);
+ //bTest = DramBaseTest( M1, RamSize - M1 * 2,SPARE, FALSE);
+ /* the memory can not correct work, this is because the user set the incorrect memory
+ parameter from setup interface.so we must set the boot mode to recovery mode, let
+ the system to reset and use the spd value to initialize the memory */
+ SetUMARam();
+ return CB_SUCCESS;
+}
diff --git a/src/northbridge/via/vx800/ddr2init/DramInit.h b/src/northbridge/via/vx800/ddr2init/DramInit.h
new file mode 100644
index 0000000000..36234bc46b
--- /dev/null
+++ b/src/northbridge/via/vx800/ddr2init/DramInit.h
@@ -0,0 +1,263 @@
+/*
+ * 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; either 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
+ */
+
+#ifndef __DRAMINIT_H_
+#define __DRAMINIT_H_
+
+//Dram Size
+#define M (1024*1024)
+#define M1 (1*M)
+#define M64 (64*M)
+#define M128 (128*M)
+#define M256 (256*M)
+#define M384 (384*M)
+#define M512 (512*M)
+
+// UMA size
+#define UMASIZE M64
+
+#define ENABLE_CHC 0 //CHC enable, how ever, this CHC,used some reg define in CHB
+#define ENABLE_CHB 0 //CHB enable , CHB is VX800's, VX855 no this CHB.
+//Dram Freq
+#define DIMMFREQ_800 400
+#define DIMMFREQ_667 333
+//#define DIMMFREQ_600 300
+#define DIMMFREQ_533 266
+#define DIMMFREQ_400 200
+#define DIMMFREQ_333 166
+#define DIMMFREQ_266 133
+#define DIMMFREQ_200 100
+
+//Dram Type
+#define RAMTYPE_FPMDRAM 1
+#define RAMTYPE_EDO 2
+#define RAMTYPE_PipelinedNibble 3
+#define RAMTYPE_SDRAM 4
+#define RAMTYPE_ROM 5
+#define RAMTYPE_SGRAMDDR 6
+#define RAMTYPE_SDRAMDDR 7
+#define RAMTYPE_SDRAMDDR2 8
+
+/* CAS latency constant */
+#define CASLAN_15 15
+#define CASLAN_2 20
+#define CASLAN_25 25
+#define CASLAN_3 30
+#define CASLAN_35 35
+#define CASLAN_4 40
+#define CASLAN_45 45
+#define CASLAN_5 50
+#define CASLAN_NULL 00
+
+//Burst length
+#define BURSTLENGTH8 8
+#define BURSTLENGTH4 4
+
+//Data Width
+//#define DATAWIDTHX16 16
+//#define DATAWIDTHX8 8
+//#define DATAWIDTHX4 4
+
+
+#define SPD_MEMORY_TYPE 2 /*Memory type FPM,EDO,SDRAM,DDR,DDR2 */
+#define SPD_SDRAM_ROW_ADDR 3 /*Number of row addresses on this assembly */
+#define SPD_SDRAM_COL_ADDR 4 /*Number of column addresses on this assembly */
+#define SPD_SDRAM_DIMM_RANKS 5 /*Number of RANKS on this assembly */
+#define SPD_SDRAM_MOD_DATA_WIDTH 6 /*Data width of this assembly */
+#define SPD_SDRAM_TCLK_X 9 /*Cycle time at Maximum supported CAS latency (CL=X) */
+#define SPD_SDRAM_TAC_X 10 /*Access time for highest CL */
+#define SPD_SDRAM_CONFIG_TYPE 11 /*Non-parity , Parity or ECC */
+#define SPD_SDRAM_REFRESH 12 /*Refresh rate/type */
+#define SPD_SDRAM_WIDTH 13 /*Primary sdram width */
+#define SPD_SDRAM_MIN_CLK_DLY 15 /*Minimum clock delay */
+#define SPD_SDRAM_BURSTLENGTH 16 /*Burst Lengths supported */
+#define SPD_SDRAM_NO_OF_BANKS 17 /*Number of banks on this assembly */
+#define SPD_SDRAM_CAS_LATENCY 18 /*CAS latency */
+#define SPD_SDRAM_DIMM_TYPE_DDR2 20 /*DIMM type information; identifies the DDR2 memory module type */
+#define SPD_SDRAM_DEV_ATTR_DDR1 20 /*WE latency */
+#define SPD_SDRAM_MODULES_ATTR 21 /*This byte depicts various aspects of the modules; DDR DDR2 have different aspects */
+#define SPD_SDRAM_DEV_ATTR_GEN 22 /*General device attributes */
+#define SPD_SDRAM_TCLK_X_1 23 /*Minimum clock cycle time at Reduced CL, DDR: X-0.5 DDR2: X-1 */
+#define SPD_SDRAM_TAC_X_1 24 /*Maximum Data Access time from Clock at reduced CL,DDR: X-0.5 DDR2: X-1 */
+#define SPD_SDRAM_TCLK_X_2 25 /*Minimum clock cycle time at reduced CL, DDR: X-1 DDR2: X-2 */
+#define SPD_SDRAM_TAC_X_2 26 /*Maximum Data Access time from Clock at reduced CL, DDR: X-1 DDR2: X-2 */
+#define SPD_SDRAM_TRP 27 /*minimum row precharge time */
+#define SPD_SDRAM_TRRD 28 /*minimum row active to row active delay */
+#define SPD_SDRAM_TRCD 29 /*minimum RAS to CAS delay */
+#define SPD_SDRAM_TRAS 30 /*minimum active to precharge time */
+#define SPD_SDRAM_TWR 36 /*write recovery time, only DDR2 use it */
+#define SPD_SDRAM_TWTR 37 /*internal write to read command delay, only DDR2 use it */
+#define SPD_SDRAM_TRTP 38 /*internal read to prechange command delay, only DDR2 use it */
+#define SPD_SDRAM_TRFC2 40 /*extension of byte 41 tRC and byte 42 tRFC, only DDR2 use it */
+#define SPC_SDRAM_TRC 41 /*minimum active to active/refresh time */
+#define SPD_SDRAM_TRFC 42 /*minimum refresh to active / refresh command period */
+
+#define SPD_DATA_SIZE 44
+//Dram cofig are
+/*the most number of socket*/
+//#define MAX_RAM_SLOTS 2
+#define MAX_SOCKETS MAX_RAM_SLOTS
+#define MAX_DIMMS MAX_SOCKETS /*every sockets can plug one DIMM */
+/*the most number of RANKs on a DIMM*/
+#define MAX_RANKS MAX_SOCKETS*2
+
+struct mem_controller {
+ u8 channel0[MAX_DIMMS];
+};
+
+static const struct mem_controller ctrl = {
+ .channel0 = {0x50, 0x51},
+};
+
+typedef struct _DRAM_CONFIG_DATA {
+ u8 DramClk;
+ u8 DramTiming;
+ u8 CasLatency;
+ u8 BankIntlv;
+ u8 Trp;
+ u8 Tras;
+ u8 Trcd;
+ u8 Trfc;
+ u8 Trrd;
+ u8 Trtp;
+ u8 Twtr;
+ u8 Twr;
+
+ u8 CmdRate;
+ u8 DualEn;
+ //u8 IntLv0;
+ //u8 IntLv1;
+ //u8 Ba0Sel;
+ //u8 Ba1Sel;
+ //u8 Ba2Sel;
+ u8 BaScmb;
+ u8 DrdyTiming;
+ //u8 Above4G;
+ //u8 RdsaitMode;
+ //u8 Rdsait;
+ //u8 TopPerf;
+
+ u16 UMASize;
+} DRAM_CONFIG_DATA;
+
+/*DIMM(assembly) information*/
+typedef struct _DIMM_INFO_tag {
+ u8 bPresence;
+ u8 SPDDataBuf[SPD_DATA_SIZE]; /*get all information from spd data */
+} DIMM_INFO;
+
+typedef struct _DRAM_SYS_ATTR_tag {
+ DIMM_INFO DimmInfo[MAX_DIMMS];
+
+ u8 RankPresentMap; /*bit0,1 Rank0,1 on DIMM0, bit2,3 Rank2,3 on DIMM1,
+ bit4,5 Rank4,5 on DIMM2, bit6,7 Rank6,7 on DIMM3 */
+ u8 DimmNumChA; /*Dimm number */
+ u8 DimmNumChB;
+ u8 RankNumChA; /*the number of Ranks on the mortherbaord */
+ u8 RankNumChB;
+ u8 LoadNumChA; /*the number of chips on all DIMM */
+ u8 LoadNumChB;
+
+ u8 DramType; /*DDR1 or DDR2 */
+ u16 DramFreq;
+ u16 DramCyc; /*10ns, 7.5ns, 6ns, 5ns, 3.75ns, 3ns, 2.5ns =1/SysFreq, unit: 100*ns. */
+
+ //u16 HFreq; /*100, 133, 166, 200, 266, 333, 400*/
+
+ u8 CL; /* CAS lantency */
+ u8 CmdRate; /*1T or 2T */
+
+ u32 RankSize[MAX_RANKS];
+ u8 Dual_Channel;
+ DRAM_CONFIG_DATA ConfigData;
+ u8 reserved[4];
+
+} DRAM_SYS_ATTR;
+
+typedef struct _DRAM_SIZE_INFO {
+ u32 RankLength[MAX_RANKS];
+} DRAM_SIZE_INFO;
+
+//detection.c
+/*Step1 detect DRAM type, Read SPD data,command rate*/
+CB_STATUS DRAMDetect(DRAM_SYS_ATTR * DramAttr);
+//FreqSetting.c
+/*Step2 set Frequency, calculate CAL*/
+void DRAMFreqSetting(DRAM_SYS_ATTR * DramAttr);
+//TimingSetting.c
+/*Step3 Set DRAM Timing*/
+void DRAMTimingSetting(DRAM_SYS_ATTR * DramAttr);
+//DRDY_BL.c
+/*Step4 DRDY*/
+void DRAMDRDYSetting(DRAM_SYS_ATTR * DramAttr);
+//DRDY_BL.c
+/*Step5 Burst Length*/
+void DRAMBurstLength(DRAM_SYS_ATTR * DramAttr);
+//DrivingSetting.c
+/*Step6 DRAM Driving Adjustment*/
+void DRAMDriving(DRAM_SYS_ATTR * DramAttr);
+
+//ClkCtrl.c
+/*Step7 duty cycle control*/
+void DutyCycleCtrl(DRAM_SYS_ATTR * DramAttr);
+//ClkCtrl.c
+/*Step8 DRAM clock phase and delay control*/
+void DRAMClkCtrl(DRAM_SYS_ATTR * DramAttr);
+
+//DevInit.c
+/*Step9 set register before init DRAM device*/
+void DRAMRegInitValue(DRAM_SYS_ATTR * DramAttr);
+
+//DevInit.c
+/*Step10 DDR and DDR2 initialize process*/
+void DRAMInitializeProc(DRAM_SYS_ATTR * DramAttr);
+
+//DQSSearch.c
+/*Step11 Search DQS and DQ output delay*/
+void DRAMDQSOutputSearch(DRAM_SYS_ATTR * DramAttr);
+
+//DQSSearch.c
+/*Step12 Search DQS input delay*/
+void DRAMDQSInputSearch(DRAM_SYS_ATTR * DramAttr);
+
+//RankMap.c
+/*Step13 Interleav function in rankmap.c*/
+void DRAMBankInterleave(DRAM_SYS_ATTR * DramAttr);
+
+//RankMap.c
+/*Step14 Sizing*/
+void DRAMSizingMATypeM(DRAM_SYS_ATTR * DramAttr);
+
+
+//FinalSetting.c
+/*Step15 DDR fresh counter setting*/
+void DRAMRefreshCounter(DRAM_SYS_ATTR * DramAttr);
+
+//FinnalSetting.c
+/*Step16 Final register setting for improve performance*/
+void DRAMRegFinalValue(DRAM_SYS_ATTR * DramAttr);
+
+
+/*set UMA*/
+void SetUMARam();
+
+CB_STATUS InstallMemory(DRAM_SYS_ATTR * DramAttr, u32 RamSize);
+CB_STATUS DDR2_DRAM_INIT();
+
+#endif
diff --git a/src/northbridge/via/vx800/ddr2init/DramUtil.c b/src/northbridge/via/vx800/ddr2init/DramUtil.c
new file mode 100644
index 0000000000..d09acdaf6f
--- /dev/null
+++ b/src/northbridge/via/vx800/ddr2init/DramUtil.c
@@ -0,0 +1,249 @@
+/*
+ * 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 WaitMicroSec(UINTN MicroSeconds)
+{
+ u32 i;
+
+ for (i = 0; i < 1024 * MicroSeconds; i++) {
+ __asm__ volatile ("nop\n\t");
+ }
+
+ return;
+}
+
+/*===================================================================
+Function : via_write_phys()
+Precondition :
+Input : addr
+ value
+Output : void
+Purpose :
+Reference : None
+===================================================================*/
+
+void via_write_phys(volatile u32 addr, volatile u32 value)
+{
+ volatile u32 *ptr;
+ ptr = (volatile u32 *) addr;
+ *ptr = (volatile u32) value;
+}
+
+/*===================================================================
+Function : via_read_phys()
+Precondition :
+Input : addr
+Output : u32
+Purpose :
+Reference : None
+===================================================================*/
+
+u32 via_read_phys(volatile u32 addr)
+{
+ volatile u32 *ptr;
+ volatile u32 y;
+// ptr = (volatile u32 *)addr;
+ y = *(volatile u32 *) addr;
+// return *ptr;
+ return y;
+}
+
+
+/*===================================================================
+Function : DimmRead()
+Precondition :
+Input : x
+Output : u32
+Purpose :
+Reference : None
+===================================================================*/
+
+u32 DimmRead(volatile u32 x)
+{ // volatile u32 z;
+ volatile u32 y;
+ y = *(volatile u32 *) x;
+
+ return y;
+}
+
+
+/*===================================================================
+Function : DramBaseTest()
+Precondition : this function used to verify memory
+Input :
+ BaseAdd,
+ length,
+ mode
+Output : u32
+Purpose :write into and read out to verify if dram is correct
+Reference : None
+===================================================================*/
+BOOLEAN DramBaseTest(u32 BaseAdd, u32 Length,
+ DRAM_TEST_MODE Mode, BOOLEAN PrintFlag)
+{
+ u32 TestSpan;
+ u32 Data, Address, Address2;
+ u8 i, TestCount;
+
+ //decide the test mode is continous or step
+ if (Mode == EXTENSIVE) {
+ //the test mode is continuos and must test each unit
+ TestSpan = 4;
+ TestCount = 1;
+ } else if (Mode == SPARE) {
+ // the test mode is step and test some unit
+ TestSpan = STEPSPAN;
+ TestCount = TESTCOUNT;
+ } else {
+ PRINT_DEBUG_MEM("the test mode is error\r");
+ return FALSE;
+ }
+
+ //write each test unit the value with TEST_PATTERN
+ for (Address = BaseAdd; Address < BaseAdd + Length;
+ Address += TestSpan) {
+ for (i = 0; i < TestCount; i++)
+ via_write_phys(Address + i * 4, TEST_PATTERN);
+ if (PrintFlag) {
+ if ((u32) Address % 0x10000000 == 0) {
+ PRINT_DEBUG_MEM("Write in Addr =");
+ PRINT_DEBUG_MEM_HEX32(Address);
+ PRINT_DEBUG_MEM("\r");
+ }
+ }
+ }
+
+ //compare each test unit with the value of TEST_PATTERN
+ //and write it with compliment of TEST_PATTERN
+ for (Address = BaseAdd; Address < BaseAdd + Length;
+ Address += TestSpan) {
+ for (i = 0; i < TestCount; i++) {
+ Data = via_read_phys(Address + i * 4);
+ via_write_phys(Address + i * 4,
+ (u32) (~TEST_PATTERN));
+ if (Data != TEST_PATTERN) {
+ PRINT_DEBUG_MEM
+ ("TEST_PATTERN ERROR !!!!! ");
+ Address2 = Address + i * 4;
+ PRINT_DEBUG_MEM_HEX32(Address2);
+ PRINT_DEBUG_MEM(" : ");
+ PRINT_DEBUG_MEM_HEX32(Data);
+ PRINT_DEBUG_MEM(" \r");
+ return FALSE;
+ }
+ }
+ if (PrintFlag) {
+ if ((u32) Address % 0x10000000 == 0) {
+ PRINT_DEBUG_MEM("Write in Addr =");
+ PRINT_DEBUG_MEM_HEX32(Address);
+ PRINT_DEBUG_MEM("\r");
+ }
+ }
+ }
+
+
+ //compare each test unit with the value of ~TEST_PATTERN
+ for (Address = BaseAdd; Address < BaseAdd + Length;
+ Address += TestSpan) {
+ for (i = (u8) (TestCount); i > 0; i--) {
+ Data = via_read_phys(Address + (i - 1) * 4);
+ if (Data != ~TEST_PATTERN) {
+
+ PRINT_DEBUG_MEM
+ ("~TEST_PATTERN ERROR !!!!! ");
+ Address2 = Address + (i - 1) * 4;
+ PRINT_DEBUG_MEM_HEX32(Address2);
+ PRINT_DEBUG_MEM(" : ");
+ PRINT_DEBUG_MEM_HEX32(Data);
+ PRINT_DEBUG_MEM(" \r");
+ return FALSE;
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+/*===================================================================
+Function : DumpRegisters()
+Precondition :
+Input :
+ pPCIPPI,
+ DevNum,
+ FuncNum
+Output : Void
+Purpose :
+Reference : None
+===================================================================*/
+
+void DumpRegisters(INTN DevNum, INTN FuncNum)
+{
+ INTN i, j;
+ u8 ByteVal;
+
+ ByteVal = 0;
+ //pci_write_config8(PCI_DEV(0, DevNum, FuncNum), 0xA1, ByteVal);
+ PRINT_DEBUG_MEM("\rDev %02x Fun %02x\r");
+ PRINT_DEBUG_MEM
+ ("\r 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f\r");
+ PRINT_DEBUG_MEM
+ ("---------------------------------------------------\r");
+ for (i = 0; i < 0x10; i++) {
+ PRINT_DEBUG_MEM_HEX32(i);
+ for (j = 0; j < 0x10; j++) {
+ ByteVal =
+ pci_read_config8(PCI_DEV(0, DevNum, FuncNum),
+ i * 0x10 + j);
+ PRINT_DEBUG_MEM_HEX8(ByteVal);
+ PRINT_DEBUG_MEM(" ");
+
+ }
+ PRINT_DEBUG_MEM("\r");
+ }
+ return;
+}
+
+
+/*===================================================================
+Function : dumpnorth()
+Precondition :
+Input :
+ pPCIPPI,
+ Func
+Output : Void
+Purpose :
+Reference : None
+===================================================================*/
+
+void dumpnorth(u8 Func)
+{
+ u16 r, c;
+ u8 ByteVal;
+ PRINT_DEBUG_MEM("Dump North!!!\r");
+ for (r = 0; r < 32; r++) {
+ for (c = (u16) (r << 3); c < (r << 3) + 8; c++) {
+ ByteVal = 0;
+ ByteVal = pci_read_config8(PCI_DEV(0, 0, Func), c);
+ PRINT_DEBUG_MEM_HEX16(c);
+ PRINT_DEBUG_MEM("= ");
+ PRINT_DEBUG_MEM_HEX8(ByteVal);
+ }
+ PRINT_DEBUG_MEM("\r");
+ }
+}
diff --git a/src/northbridge/via/vx800/ddr2init/DramUtil.h b/src/northbridge/via/vx800/ddr2init/DramUtil.h
new file mode 100644
index 0000000000..725fd670fc
--- /dev/null
+++ b/src/northbridge/via/vx800/ddr2init/DramUtil.h
@@ -0,0 +1,47 @@
+/*
+ * 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
+ */
+
+#ifndef __DRAM_UTIL_H__
+#define __DRAM_UTIL_H__
+
+#define STEPSPAN 0x1000 //the span when test memory in spare mode
+#define TESTCOUNT 0x4 // the test count in each range when test memory in spare mode
+#define TEST_PATTERN 0x5A5A5A5A //the test pattern
+
+typedef enum __DRAM_TEST_MODE {
+ EXTENSIVE,
+ SPARE,
+ MAXMODE
+} DRAM_TEST_MODE;
+
+void WaitMicroSec(UINTN MicroSeconds);
+
+void via_write_phys(u32 addr, u32 value);
+
+u32 via_read_phys(u32 addr);
+
+u32 DimmRead(u32 x);
+
+BOOLEAN DramBaseTest(u32 BaseAdd, u32 Length,
+ DRAM_TEST_MODE mode, BOOLEAN PrintFlag);
+
+void DumpRegisters(INTN DevNum, INTN FuncNum);
+
+void dumpnorth(u8 Func);
+#endif
diff --git a/src/northbridge/via/vx800/ddr2init/Translatorddr2init.c b/src/northbridge/via/vx800/ddr2init/Translatorddr2init.c
new file mode 100644
index 0000000000..cb54aba1af
--- /dev/null
+++ b/src/northbridge/via/vx800/ddr2init/Translatorddr2init.c
@@ -0,0 +1,34 @@
+/*
+ * 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
+ */
+
+#define CB_SUCCESS 0x0
+#define CB_INVALID_PARAMETER 0x2
+#define CB_NOT_READY 0x6
+#define CB_DEVICE_ERROR 0x7
+#define TRUE 1
+#define FALSE 0
+
+
+typedef int8_t INT8;
+typedef unsigned long uintn_t;
+typedef uintn_t UINTN;
+typedef long intn_t;
+typedef intn_t INTN;
+typedef UINTN CB_STATUS;
+typedef uint8_t BOOLEAN;
diff --git a/src/northbridge/via/vx800/ddr2init/vx800/ClkCtrl.c b/src/northbridge/via/vx800/ddr2init/vx800/ClkCtrl.c
new file mode 100644
index 0000000000..13edc1f996
--- /dev/null
+++ b/src/northbridge/via/vx800/ddr2init/vx800/ClkCtrl.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);
+
+}
diff --git a/src/northbridge/via/vx800/ddr2init/vx800/DQSSearch.c b/src/northbridge/via/vx800/ddr2init/vx800/DQSSearch.c
new file mode 100644
index 0000000000..80749f8597
--- /dev/null
+++ b/src/northbridge/via/vx800/ddr2init/vx800/DQSSearch.c
@@ -0,0 +1,98 @@
+/*
+ * 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 SetDQSOutputCHA(DRAM_SYS_ATTR * DramAttr);
+void SetDQSOutputCHB(DRAM_SYS_ATTR * DramAttr);
+
+/*===================================================================
+Function : DRAMDQSOutputSearchCHA()
+Precondition :
+Input :
+ DramAttr: pointer point to DRAM_SYS_ATTR which consist the DDR and Dimm information
+ in MotherBoard
+Output : Void
+Purpose : set DQS output delay register reg70 and DQ output delay register reg71
+===================================================================*/
+
+#define CH_A 0
+#define CH_B 1
+void DRAMDQSOutputSearch(DRAM_SYS_ATTR * DramAttr)
+{
+ if (DramAttr->RankNumChA > 0)
+ SetDQSOutputCHA(DramAttr);
+}
+
+/*===================================================================
+Function : SetDQSOutputCHA()
+Precondition :
+Input :
+ DramAttr: pointer point to DRAM_SYS_ATTR which consist the DDR and Dimm information
+ in MotherBoard
+Output : Void
+Purpose : according the frequence set CHA DQS output
+===================================================================*/
+void SetDQSOutputCHA(DRAM_SYS_ATTR * DramAttr)
+{
+ u8 Reg70, Reg71;
+ u8 Index;
+
+ if (DramAttr->DramFreq == DIMMFREQ_400)
+ Index = 3;
+ else if (DramAttr->DramFreq == DIMMFREQ_533)
+ Index = 2;
+ else if (DramAttr->DramFreq == DIMMFREQ_667)
+ Index = 1;
+ else if (DramAttr->DramFreq == DIMMFREQ_800)
+ Index = 0;
+ else
+ Index = 3;
+
+ if (DramAttr->RankNumChA > 2) {
+ Reg70 = Fixed_DQSA_3_4_Rank_Table[Index][0];
+ Reg71 = Fixed_DQSA_3_4_Rank_Table[Index][1];
+ } else {
+ Reg70 = Fixed_DQSA_1_2_Rank_Table[Index][0];
+ Reg71 = Fixed_DQSA_1_2_Rank_Table[Index][1];
+ }
+ pci_write_config8(MEMCTRL, 0x70, Reg70);
+ pci_write_config8(MEMCTRL, 0x71, Reg71);
+}
+
+
+//################
+// STEP 12 #
+//################
+
+/*===================================================================
+Function : DRAMDQSInputSearch()
+Precondition :
+Input :
+ DramAttr: pointer point to DRAM_SYS_ATTR which consist the DDR and Dimm information
+ in MotherBoard
+Output : Void
+Purpose : search DQS input delay for CHA/CHB
+===================================================================*/
+
+void DRAMDQSInputSearch(DRAM_SYS_ATTR * DramAttr)
+{
+ u8 Data;
+ //auto mode
+ Data = 0x0;
+ pci_write_config8(MEMCTRL, 0x77, Data);
+}
diff --git a/src/northbridge/via/vx800/ddr2init/vx800/DRDY_BL.c b/src/northbridge/via/vx800/ddr2init/vx800/DRDY_BL.c
new file mode 100644
index 0000000000..b5a78f1a7d
--- /dev/null
+++ b/src/northbridge/via/vx800/ddr2init/vx800/DRDY_BL.c
@@ -0,0 +1,600 @@
+/*
+ * 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
+ */
+
+// Set P6IF DRDY Timing
+// Because there are 1.5T & 2.5T CAS latency in DDR1 mode, we need to use RDELAYMD-0
+//
+// Entry:
+// EBP[29:25] = DRAM Speed, Dual_Channel
+// VIA_NB2HOST_REG54[7:5] Host Frequency
+// VIA_NB3DRAM_REG62[2:0] CAS Latency
+//
+// Modify NB_Reg:
+// VIA_NB2HOST_REG54[3,1]
+// VIA_NB2HOST_REG55[1]
+// VIA_NB2HOST_REG60
+// VIA_NB2HOST_REG61
+// VIA_NB2HOST_REG62[3:0]
+// VIA_NB2HOST_REG63
+// VIA_NB2HOST_REG64
+// VIA_NB2HOST_REG65[3:0]
+// VIA_NB2HOST_REG66
+// VIA_NB2HOST_REG67[5:4]
+//
+// Processing:
+//--------------------------------------------------------------------------
+// P6IF DRDY Timing Control:
+// *Following algorithm to set DRDY timing
+// Set P6IF DRDY Timing by the following 3 conditions:
+// 1. RDELAYMD
+// a.RDRPH(MD input internal timing control)
+// b.CAS Latency
+// RDELAYMD(1bit) = bit0 of (CL + RDRPH)
+// for example: RDRPH=10b, CL3 -> F3_Rx56[5:4]=11b, 10b + 11b = 101b, RDELAYMD=1 (bit0)
+// RDRPH=00b, CL2.5 -> F3_Rx56[5:4]=10b, 00b + 10b = 010b, RDELAYMD=0 (bit0)
+// 2. CPU Frequency
+// 3. DRAM Frequency
+//
+// According to above conditions, we create different tables:
+// 1. RDELAYMD=0 : for integer CAS latency(ex. CL=3)
+// 2. RDELAYMD=1 : for non-integer CAS latency(ex. CL=2.5)
+// 3. Normal performance
+// 4. Top performance :
+// Using phase0 to a case has better performance.
+//
+// Note: The setting are related to performance and maybe affect DRAM initialize.
+// Turn OFF(F2_Rx51[7]=0) this feature at csDRAMRegInitValueJ procedure.
+// Turn ON(F2_Rx51[7]=1) this feature at csDRAMRegFinalValueJ procedure.
+//
+// If F2_Rx51[7]=0, then CPU always wait 8QW, a slower but most stable way
+// If F2_Rx51[7]=1, then the timing will refer to F2_Rx60 ~ F2_Rx67,
+// a fast way but may cause the system to be unstable.
+//
+// Coding:
+// 1. RDELAYMD and user's option for performance can determine which table
+// 2. CPU Frequency can get block offset of table
+// 3. DRAM Frequency can get row offset of block
+// 4. Set value
+//
+// PS: Fun2 Rx62, Rx65, Rx67 are don't care bits in 3296, CPU 266MHz doesn't be supported by 3296,
+// but I still keep these bits in table to avoid the usage in future
+// and do the fewest modification for code.
+//
+
+// Early 3T
+// Early 3T
+#define P6IF_Misc_RFASTH 0x08
+#define P6IF_Misc2_RRRDYH3E 0x10
+#define P6IF_Misc2_RHTSEL 0x02
+
+#define Rx54E3T P6IF_Misc_RFASTH
+#define Rx55E3T P6IF_Misc2_RRRDYH3E
+
+// Early 2T
+#define Rx54E2T 0x00
+#define Rx55E2T P6IF_Misc2_RRRDYH3E
+
+// Early 1T
+#define Rx54E1T 0x00
+#define Rx55E1T 0x00
+
+// Early 0T
+#define Rx54E0T P6IF_Misc_RFASTH
+#define Rx55E0T P6IF_Misc2_RRRDYH3E + P6IF_Misc2_RHTSEL
+
+// Latter 1T
+#define Rx54L1T P6IF_Misc_RFASTH
+#define Rx55L1T P6IF_Misc2_RHTSEL
+
+
+#define PH0_0_0_0 0x00
+#define PH0_0_0_1 0x01
+#define PH0_0_0_2 0x02
+#define PH0_0_0_3 0x03
+#define PH0_0_1_0 0x04
+#define PH0_0_1_1 0x05
+#define PH0_0_1_2 0x06
+#define PH0_0_2_1 0x09
+#define PH0_0_2_2 0x0a
+#define PH0_0_2_3 0x0b
+#define PH0_0_3_2 0x0e
+#define PH0_0_3_3 0x0f
+#define PH0_1_1_0 0x14
+#define PH0_1_1_1 0x15
+#define PH0_2_1_2 0x26
+#define PH0_2_2_1 0x29
+#define PH0_2_2_2 0x2a
+#define PH0_2_2_3 0x2b
+#define PH0_2_3_2 0x2e
+#define PH0_2_3_3 0x2f
+#define PH0_3_2_2 0x3a
+#define PH0_3_3_3 0x3f
+#define PH1_0_0_0 0x40
+#define PH1_0_0_1 0x41
+#define PH1_0_1_1 0x45
+#define PH1_1_1_1 0x55
+#define PH1_2_1_1 0x65
+#define PH1_2_2_1 0x69
+#define PH2_1_1_1 0x95
+#define PH2_1_2_1 0x99
+#define PH2_1_2_2 0x9a
+#define PH2_2_1_2 0xa6
+#define PH2_2_2_1 0xa9
+#define PH2_2_2_2 0xaa
+#define PH2_2_3_2 0xae
+#define PH2_2_3_3 0xaf
+#define PH2_3_2_2 0xba
+#define PH2_3_2_3 0xbb
+#define PH2_3_3_2 0xbe
+#define PH3_2_2_3 0xeb
+#define PH3_2_3_2 0xee
+#define PH3_2_3_3 0xef
+#define PH3_3_3_3 0xff
+
+#define PT894_RDRDY_TBL_Width 10
+#define PT894_RDRDY_TBL_Block 60
+
+static const u8 PT894_128bit_DELAYMD0_RCONV0[6][6][PT894_RDRDY_TBL_Width] =
+// -----------------------------------------------------------------------------------------------------------------
+// RX60 RX61 RX62 RX63 RX64 RX65 RX66 RX67 RX54[3,1] RX55[3,1] CPU/DRAM
+// LN4:1 LN8:5 LN10:9 QW4:1 QW8:5 QW10:9 WS8:1 WS10:9 RFASTH RRRDYH3E
+// RCONV RHTSEL
+// -----------------------------------------------------------------------------------------------------------------
+{
+// cpu100
+ {
+ {PH0_1_1_1, PH0_0_0_0, PH0_0_0_0, PH0_1_1_1, PH0_0_0_0, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T}, // 100/100
+ {PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T}, // 100/133
+ {PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T}, // 100/166
+ {PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T}, // 100/200
+ {PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T}, // 100/266
+ {PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T} // 100/333
+ },
+// cpu133
+ {
+ {PH0_2_2_1, PH0_0_0_0, PH0_0_0_0, PH0_2_2_1, PH0_0_0_0, PH0_0_0_0, 0x01, 0x00, Rx54E3T, Rx55E3T}, // 133/100
+ {PH1_1_1_1, PH0_0_0_0, PH0_0_0_0, PH1_1_1_1, PH0_0_0_0, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T}, // 133/133
+ {PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T}, // 133/166
+ {PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T}, // 133/200
+ {PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T}, // 133/266
+ {PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T} // 133/333
+ },
+// cpu200
+ {
+ {PH0_3_3_3, PH0_0_0_0, PH0_0_0_0, PH0_2_2_2, PH0_0_0_0, PH0_0_0_0, 0x07, 0x00, Rx54E2T, Rx55E2T}, // 200/100
+ {PH2_3_2_3, PH0_0_0_0, PH0_0_0_0, PH2_3_2_3, PH0_0_0_0, PH0_0_0_0, 0x0a, 0x00, Rx54E3T, Rx55E3T}, // 200/133
+ {PH1_2_2_1, PH0_0_0_1, PH0_0_0_0, PH1_2_2_1, PH0_0_0_1, PH0_0_0_0, 0x01, 0x00, Rx54E3T, Rx55E3T}, // 200/166
+ {PH1_1_1_1, PH0_0_1_1, PH0_0_0_0, PH1_1_1_1, PH0_0_1_1, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T}, // 200/200
+ {PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T}, // 200/266
+ {PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T} // 200/333
+ },
+// cpu166
+ {
+ {PH0_2_3_3, PH0_0_0_0, PH0_0_0_0, PH0_2_2_3, PH0_0_0_0, PH0_0_0_0, 0x05, 0x00, Rx54E3T, Rx55E3T}, // 166/100
+ {PH1_2_2_1, PH0_0_0_0, PH0_0_0_0, PH1_2_2_1, PH0_0_0_0, PH0_0_0_0, 0x01, 0x00, Rx54E3T, Rx55E3T}, // 166/133
+ {PH1_1_1_1, PH0_0_0_1, PH0_0_0_0, PH1_1_1_1, PH0_0_0_1, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T}, // 166/166
+ {PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T}, // 166/200
+ {PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T}, // 166/266
+ {PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T} // 166/333
+ },
+// cpu266
+ {
+ {PH0_2_2_3, PH0_0_0_0, PH0_0_0_0, PH0_0_1_1, PH0_0_0_0, PH0_0_0_0, 0x07, 0x00, Rx54E1T, Rx55E1T}, // 266/100
+ {PH3_3_3_3, PH0_0_0_0, PH0_0_0_0, PH2_2_2_2, PH0_0_0_0, PH0_0_0_0, 0x0f, 0x00, Rx54E2T, Rx55E2T}, // 266/133
+ {PH3_2_3_3, PH0_0_0_3, PH0_0_0_0, PH3_2_3_3, PH0_0_0_2, PH0_0_0_0, 0x0d, 0x00, Rx54E3T, Rx55E3T}, // 266/166
+ {PH2_2_2_2, PH0_0_2_2, PH0_0_0_0, PH2_1_2_2, PH0_0_1_2, PH0_0_0_0, 0x12, 0x00, Rx54E3T, Rx55E3T}, // 266/200
+ {PH1_1_1_1, PH1_1_1_1, PH0_0_0_0, PH1_1_1_1, PH1_1_1_1, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T}, // 266/266
+ {PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T} // 266/333
+ },
+// cpu333
+ {
+ {PH0_1_1_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x07, 0x00, Rx54E0T, Rx55E0T}, // 333/100
+ {PH1_1_1_1, PH0_0_0_0, PH0_0_0_0, PH1_1_1_1, PH0_0_0_0, PH0_0_0_0, 0x0f, 0x00, Rx54E1T, Rx55E1T}, // 333/133
+ {PH3_3_3_3, PH0_0_0_3, PH0_0_0_0, PH3_3_3_3, PH0_0_0_3, PH0_0_0_0, 0x1f, 0x00, Rx54E2T, Rx55E2T}, // 333/166
+ {PH2_2_1_2, PH0_0_2_1, PH0_0_0_0, PH1_2_1_1, PH0_0_2_1, PH0_0_0_0, 0x36, 0x00, Rx54E2T, Rx55E2T}, // 333/200
+ {PH2_1_1_1, PH2_1_1_1, PH0_0_0_0, PH2_1_1_1, PH2_1_1_1, PH0_0_0_0, 0x44, 0x00, Rx54E3T, Rx55E3T}, // 333/266
+ {PH2_2_2_2, PH2_2_2_2, PH0_0_2_2, PH2_2_2_2, PH2_2_2_2, PH0_0_2_2, 0x00, 0x00, Rx54E3T, Rx55E3T} // 333/333
+ }
+};
+
+static const u8 PT894_128bit_DELAYMD1_RCONV0[6][6][PT894_RDRDY_TBL_Width] =
+// -----------------------------------------------------------------------------------------------------------------
+// RX60 RX61 RX62 RX63 RX64 RX65 RX66 RX67 RX54[3,1] RX55[3,1] CPU/DRAM
+// LN4:1 LN8:5 LN10:9 QW4:1 QW8:5 QW10:9 WS8:1 WS10:9 RFASTH RRRDYH3E
+// RCONV RHTSEL
+// -----------------------------------------------------------------------------------------------------------------
+{
+// cpu100
+ {
+ {PH0_1_1_1, PH0_0_0_0, PH0_0_0_0, PH0_1_1_1, PH0_0_0_0, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T}, // 100/100
+ {PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T}, // 100/133
+ {PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T}, // 100/166
+ {PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T}, // 100/200
+ {PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T}, // 100/266
+ {PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T} // 100/333
+ },
+// cpu133
+ {
+ {PH0_3_2_2, PH0_0_0_0, PH0_0_0_0, PH0_3_2_2, PH0_0_0_0, PH0_0_0_0, 0x02, 0x00, Rx54E3T, Rx55E3T}, // 133/100
+ {PH1_1_1_1, PH0_0_0_0, PH0_0_0_0, PH1_1_1_1, PH0_0_0_0, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T}, // 133/133
+ {PH1_0_0_0, PH0_0_0_0, PH0_0_0_0, PH1_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T}, // 133/166
+ {PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T}, // 133/200
+ {PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T}, // 133/266
+ {PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T} // 133/333
+ },
+// cpu200
+ {
+ {PH0_2_2_2, PH0_0_0_0, PH0_0_0_0, PH0_1_1_1, PH0_0_0_0, PH0_0_0_0, 0x07, 0x00, Rx54E1T, Rx55E1T}, // 200/100
+ {PH2_2_2_2, PH0_0_0_0, PH0_0_0_0, PH2_1_2_1, PH0_0_0_0, PH0_0_0_0, 0x0a, 0x00, Rx54E2T, Rx55E2T}, // 200/133
+ {PH2_2_2_2, PH0_0_0_2, PH0_0_0_0, PH2_2_2_2, PH0_0_0_2, PH0_0_0_0, 0x04, 0x00, Rx54E3T, Rx55E3T}, // 200/166
+ {PH2_2_2_2, PH0_0_2_2, PH0_0_0_0, PH2_2_2_2, PH0_0_2_2, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T}, // 200/200
+ {PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T}, // 200/266
+ {PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T} // 200/333
+ },
+// cpu166
+ {
+ {PH0_2_2_2, PH0_0_0_0, PH0_0_0_0, PH0_2_1_2, PH0_0_0_0, PH0_0_0_0, 0x05, 0x00, Rx54E2T, Rx55E2T}, // 166/100
+ {PH2_3_2_2, PH0_0_0_0, PH0_0_0_0, PH2_2_2_2, PH0_0_0_0, PH0_0_0_0, 0x02, 0x00, Rx54E3T, Rx55E3T}, // 166/133
+ {PH2_2_2_2, PH0_0_0_2, PH0_0_0_0, PH2_2_2_2, PH0_0_0_2, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T}, // 166/166
+ {PH1_0_0_0, PH0_0_0_1, PH0_0_0_0, PH1_0_0_0, PH0_0_0_1, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T}, // 166/200
+ {PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T}, // 166/266
+ {PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T} // 166/333
+ },
+// cpu266
+ {
+ {PH0_1_1_1, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x07, 0x00, Rx54E0T, Rx55E0T}, // 266/100
+ {PH2_2_2_2, PH0_0_0_0, PH0_0_0_0, PH1_1_1_1, PH0_0_0_0, PH0_0_0_0, 0x0f, 0x00, Rx54E1T, Rx55E1T}, // 266/133
+ {PH2_2_2_2, PH0_0_0_2, PH0_0_0_0, PH2_2_1_2, PH0_0_0_2, PH0_0_0_0, 0x15, 0x00, Rx54E2T, Rx55E2T}, // 266/166
+ {PH3_2_3_3, PH0_0_2_3, PH0_0_0_0, PH2_2_3_2, PH0_0_2_3, PH0_0_0_0, 0x24, 0x00, Rx54E3T, Rx55E3T}, // 266/200
+ {PH2_2_2_2, PH2_2_2_2, PH0_0_0_0, PH2_2_2_2, PH2_2_2_2, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T}, // 266/266
+ {PH0_0_0_1, PH0_0_1_1, PH0_0_1_0, PH0_0_0_1, PH0_0_1_1, PH0_0_1_0, 0x00, 0x00, Rx54E3T, Rx55E3T} // 266/333
+ },
+// cpu333
+ {
+ {PH0_3_2_2, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x07, 0x00, Rx54E0T, Rx55E0T}, // 333/100
+ {PH1_1_1_1, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x0f, 0x00, Rx54E0T, Rx55E0T}, // 333/133
+ {PH2_2_2_2, PH0_0_0_2, PH0_0_0_0, PH2_2_2_2, PH0_0_0_2, PH0_0_0_0, 0x1f, 0x00, Rx54E1T, Rx55E1T}, // 333/166
+ {PH2_3_2_2, PH0_0_3_2, PH0_0_0_0, PH2_2_2_2, PH0_0_2_2, PH0_0_0_0, 0x1b, 0x00, Rx54E2T, Rx55E2T}, // 333/200
+ {PH2_2_2_2, PH2_2_2_2, PH0_0_0_0, PH2_2_2_1, PH2_2_2_1, PH0_0_0_0, 0x88, 0x00, Rx54E3T, Rx55E3T}, // 333/266
+ {PH2_2_2_2, PH2_2_2_2, PH0_0_2_2, PH2_2_2_2, PH2_2_2_2, PH0_0_2_2, 0x00, 0x00, Rx54E3T, Rx55E3T} // 333/333
+ }
+};
+
+
+static const u8 PT894_64bit_DELAYMD0_RCONV0[6][6][PT894_RDRDY_TBL_Width] =
+// -----------------------------------------------------------------------------------------------------------------
+// RX60 RX61 RX62 RX63 RX64 RX65 RX66 RX67 RX54[3,1] RX55[3,1] CPU/DRAM
+// LN4:1 LN8:5 LN10:9 QW4:1 QW8:5 QW10:9 WS8:1 WS10:9 RFASTH RRRDYH3E
+// RCONV RHTSEL
+// -----------------------------------------------------------------------------------------------------------------
+{
+// cpu100
+ {
+ {PH0_2_2_2, PH0_0_0_0, PH0_0_0_0, PH0_1_1_1, PH0_0_0_0, PH0_0_0_0, 0x07, 0x00, Rx54E3T, Rx55E3T}, // 100/100
+ {PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x09, 0x00, Rx54E3T, Rx55E3T}, // 100/133
+ {PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T}, // 100/166
+ {PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T}, // 100/200
+ {PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T}, // 100/266
+ {PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T} // 100/333
+ },
+// cpu133
+ {
+ {PH0_2_3_2, PH0_0_0_0, PH0_0_0_0, PH0_0_1_0, PH0_0_0_0, PH0_0_0_0, 0x07, 0x00, Rx54E2T, Rx55E2T}, // 133/100
+ {PH2_2_2_2, PH0_0_0_0, PH0_0_0_0, PH1_1_1_1, PH0_0_0_0, PH0_0_0_0, 0x0f, 0x00, Rx54E3T, Rx55E3T}, // 133/133
+ {PH1_0_0_0, PH0_0_0_1, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x07, 0x00, Rx54E3T, Rx55E3T}, // 133/166
+ {PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T}, // 133/200
+ {PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T}, // 133/266
+ {PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T} // 133/333
+ },
+// cpu200
+ {
+ {PH0_3_3_3, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x07, 0x00, Rx54E0T, Rx55E0T}, // 200/100
+ {PH2_2_2_2, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x0f, 0x00, Rx54E1T, Rx55E1T}, // 200/133
+ {PH3_3_3_3, PH0_0_0_3, PH0_0_0_0, PH1_2_2_1, PH0_0_0_1, PH0_0_0_0, 0x1f, 0x00, Rx54E3T, Rx55E3T}, // 200/166
+ {PH2_2_2_2, PH0_0_2_2, PH0_0_0_0, PH1_1_1_1, PH0_0_1_1, PH0_0_0_0, 0x3f, 0x00, Rx54E3T, Rx55E3T}, // 200/200
+ {PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x00, 0x00, Rx54E1T, Rx55E1T}, // 200/266
+ {PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T} // 200/333
+// DDR2 Both E3T and E2T Fail, need set to E1T, db PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 00110011b, 00000000b, Rx54E3T, Rx55E3T ;200/266
+ },
+// cpu166
+ {
+ {PH0_2_3_2, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x07, 0x00, Rx54E1T, Rx55E1T}, // 166/100
+ {PH2_2_2_2, PH0_0_0_0, PH0_0_0_0, PH0_0_1_0, PH0_0_0_0, PH0_0_0_0, 0x0f, 0x00, Rx54E2T, Rx55E2T}, // 166/133
+ {PH2_2_2_2, PH0_0_0_2, PH0_0_0_0, PH1_1_1_1, PH0_0_0_1, PH0_0_0_0, 0x1f, 0x00, Rx54E3T, Rx55E3T}, // 166/166
+ {PH1_0_0_1, PH0_0_1_1, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x1e, 0x00, Rx54E3T, Rx55E3T}, // 166/200
+ {PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T}, // 166/266
+ {PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T} // 166/333
+ },
+// cpu266
+ {
+ {PH0_2_2_2, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x07, 0x00, Rx54L1T, Rx55L1T}, // 266/100
+ {PH1_1_1_1, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x0f, 0x00, Rx54L1T, Rx55L1T}, // 266/133
+ {PH3_2_3_2, PH0_0_0_2, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x1f, 0x00, Rx54E1T, Rx55E1T}, // 266/166
+ {PH3_2_2_3, PH0_0_2_2, PH0_0_0_0, PH1_0_0_1, PH0_0_0_0, PH0_0_0_0, 0x3f, 0x00, Rx54E2T, Rx55E2T}, // 266/200
+ {PH2_2_2_2, PH2_2_2_2, PH0_0_0_0, PH1_1_1_1, PH1_1_1_1, PH0_0_0_0, 0xff, 0x00, Rx54E3T, Rx55E3T}, // 266/266
+ {PH0_0_1_1, PH0_1_1_1, PH0_0_1_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x9c, 0x03, Rx54E3T, Rx55E3T} // 266/333
+ },
+// cpu333
+ {
+ {PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x00, 0x00, Rx54L1T, Rx55L1T}, // 333/100 ;DO NOT Support
+ {PH2_2_2_2, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x0f, 0x00, Rx54L1T, Rx55L1T}, // 333/133
+ {PH3_3_3_3, PH0_0_0_3, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x1f, 0x00, Rx54E0T, Rx55E0T}, // 333/166
+ {PH2_3_3_2, PH0_0_3_3, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x3f, 0x00, Rx54E1T, Rx55E1T}, // 333/200
+ {PH3_3_3_3, PH3_3_3_3, PH0_0_0_0, PH2_1_1_1, PH2_1_1_1, PH0_0_0_0, 0xff, 0x00, Rx54E3T, Rx55E3T}, // 333/266
+ {PH2_2_2_2, PH2_2_2_2, PH0_0_2_2, PH2_2_2_2, PH2_2_2_2, PH0_0_2_2, 0xff, 0x03, Rx54E3T, Rx55E3T} // 333/333
+ }
+};
+
+
+static const u8 PT894_64bit_DELAYMD1_RCONV0[6][6][PT894_RDRDY_TBL_Width] =
+// -----------------------------------------------------------------------------------------------------------------
+// RX60 RX61 RX62 RX63 RX64 RX65 RX66 RX67 RX54[3,1] RX55[3,1] CPU/DRAM
+// LN4:1 LN8:5 LN10:9 QW4:1 QW8:5 QW10:9 WS8:1 WS10:9 RFASTH RRRDYH3E
+// RCONV RHTSEL
+// -----------------------------------------------------------------------------------------------------------------
+{
+// cpu100
+ {
+ {PH0_2_2_2, PH0_0_0_0, PH0_0_0_0, PH0_1_1_1, PH0_0_0_0, PH0_0_0_0, 0x07, 0x00, Rx54E3T, Rx55E3T}, // 100/100
+ {PH1_0_0_1, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x06, 0x00, Rx54E3T, Rx55E3T}, // 100/133
+ {PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T}, // 100/166
+ {PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T}, // 100/200
+ {PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T}, // ;100/266
+ {PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T} // 100/333
+ },
+// cpu133
+ {
+ {PH0_3_3_3, PH0_0_0_0, PH0_0_0_0, PH0_1_1_1, PH0_0_0_0, PH0_0_0_0, 0x07, 0x00, Rx54E2T, Rx55E2T}, // 133/100
+ {PH2_2_2_2, PH0_0_0_0, PH0_0_0_0, PH1_1_1_1, PH0_0_0_0, PH0_0_0_0, 0x0f, 0x00, Rx54E3T, Rx55E3T}, // 133/133
+ {PH1_0_1_1, PH0_0_0_1, PH0_0_0_0, PH1_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x1c, 0x00, Rx54E3T, Rx55E3T}, // 133/166
+ {PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x09, 0x00, Rx54E3T, Rx55E3T}, // 133/200
+ {PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T}, // 133/266
+ {PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T} // 133/333
+ },
+// cpu200
+ {
+ {PH0_2_2_2, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x07, 0x00, Rx54L1T, Rx55L1T}, // 200/100
+ {PH3_3_3_3, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x0f, 0x00, Rx54E1T, Rx55E1T}, // 200/133
+ {PH2_2_3_3, PH0_0_0_2, PH0_0_0_0, PH1_0_1_1, PH0_0_0_1, PH0_0_0_0, 0x1f, 0x00, Rx54E2T, Rx55E2T}, // 200/166
+ {PH3_3_3_3, PH0_0_3_3, PH0_0_0_0, PH2_2_2_2, PH0_0_2_2, PH0_0_0_0, 0x3f, 0x00, Rx54E3T, Rx55E3T}, // 200/200
+ {PH0_0_1_1, PH0_0_1_1, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0xcc, 0x00, Rx54E3T, Rx55E3T}, // 200/266
+ {PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T} // 200/333
+ },
+// cpu166
+ {
+ {PH0_3_3_3, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x07, 0x00, Rx54E1T, Rx55E1T}, // 166/100
+ {PH2_2_3_3, PH0_0_0_0, PH0_0_0_0, PH1_0_1_1, PH0_0_0_0, PH0_0_0_0, 0x0f, 0x00, Rx54E2T, Rx55E2T}, // 166/133
+ {PH2_2_2_2, PH0_0_0_2, PH0_0_0_0, PH2_2_2_2, PH0_0_0_2, PH0_0_0_0, 0x1f, 0x00, Rx54E3T, Rx55E3T}, // 166/166
+ {PH1_1_1_1, PH0_0_1_1, PH0_0_0_0, PH1_0_0_0, PH0_0_0_1, PH0_0_0_0, 0x39, 0x00, Rx54E3T, Rx55E3T}, // 166/200
+ {PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T}, // 166/266
+ {PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x00, 0x00, Rx54E3T, Rx55E3T} // 166/333
+ },
+// cpu266
+ {
+ {PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x00, 0x00, Rx54L1T, Rx55L1T}, // 266/100 ;DO NOT Support
+ {PH2_2_2_2, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x0f, 0x00, Rx54L1T, Rx55L1T}, // 266/133
+ {PH2_2_1_2, PH0_0_0_1, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x1f, 0x00, Rx54E0T, Rx55E0T}, // 266/166
+ {PH3_3_3_3, PH0_0_3_3, PH0_0_0_0, PH1_1_1_1, PH0_0_1_1, PH0_0_0_0, 0x3f, 0x00, Rx54E2T, Rx55E2T}, // 266/200
+ {PH3_3_3_3, PH3_3_3_3, PH0_0_0_0, PH2_2_2_2, PH2_2_2_2, PH0_0_0_0, 0xff, 0x00, Rx54E3T, Rx55E3T}, // 266/266
+ {PH1_1_1_1, PH1_1_1_1, PH0_0_1_1, PH0_0_0_1, PH0_0_1_1, PH0_0_1_0, 0x73, 0x02, Rx54E3T, Rx55E3T} // 266/333
+ },
+// cpu333
+ {
+ {PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x00, 0x00, Rx54L1T, Rx55L1T}, // 333/100 ;DO NOT Support
+ {PH3_3_3_3, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x0f, 0x00, Rx54L1T, Rx55L1T}, // 333/133
+ {PH2_2_2_2, PH0_0_0_2, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x1f, 0x00, Rx54L1T, Rx55L1T}, // 333/166
+ {PH2_2_2_2, PH0_0_2_2, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, PH0_0_0_0, 0x3f, 0x00, Rx54E1T, Rx55E1T}, // 333/200
+ {PH2_3_2_2, PH2_3_2_2, PH0_0_0_0, PH0_1_1_0, PH0_1_1_0, PH0_0_0_0, 0xff, 0x00, Rx54E2T, Rx55E2T}, // 333/266
+ {PH3_3_3_3, PH3_3_3_3, PH0_0_3_3, PH2_2_2_2, PH2_2_2_2, PH0_0_2_2, 0xff, 0x03, Rx54E3T, Rx55E3T} // 333/333
+ }
+};
+
+void DRAMDRDYSetting(DRAM_SYS_ATTR * DramAttr)
+{
+ u8 Data, CL, RDRPH;
+ u8 CpuFreq, DramFreq;
+ u8 ProgData[PT894_RDRDY_TBL_Width];
+ u8 DelayMode;
+ u8 DrdyMode;
+ u8 Index;
+
+ /*
+ this function has 3 switchs, correspond to 3 level of Drdy setting.
+ 0:Slowest, 1:Default, 2:Optimize
+ you can only open one switch
+ */
+#if 1 //this is slowest
+ // 0 -> Slowest
+ //Write slowest value to register
+
+ Data = 0xAA;
+ pci_write_config8(PCI_DEV(0, 0, 2), 0x60, Data);
+
+ Data = 0x0A;
+ pci_write_config8(PCI_DEV(0, 0, 2), 0x61, Data);
+
+ Data = 0x00;
+ pci_write_config8(PCI_DEV(0, 0, 2), 0x62, Data);
+
+ Data = 0xAA;
+ pci_write_config8(PCI_DEV(0, 0, 2), 0x63, Data);
+
+ Data = 0x0A;
+ pci_write_config8(PCI_DEV(0, 0, 2), 0x64, Data);
+
+ Data = 0x00;
+ pci_write_config8(PCI_DEV(0, 0, 2), 0x65, Data);
+
+ Data = 0x00;
+ pci_write_config8(PCI_DEV(0, 0, 2), 0x66, Data);
+
+ Data = 0x00;
+ pci_write_config8(PCI_DEV(0, 0, 2), 0x67, Data);
+
+ Data = pci_read_config8(PCI_DEV(0, 0, 2), 0x54);
+ Data = Data & 0xF5;
+ Data |= 0x08;
+ pci_write_config8(PCI_DEV(0, 0, 2), 0x54, Data);
+
+ //Data=pci_read_config8(PCI_DEV(0,0,2), 0x55);
+ //Data = Data & (~0x20);
+ //pci_write_config8(PCI_DEV(0,0,2), 0x55, Data);
+
+ //enable drdy timing
+ Data = pci_read_config8(PCI_DEV(0, 0, 2), 0x51);
+ Data = Data | 0x80;
+ pci_write_config8(PCI_DEV(0, 0, 2), 0x51, Data);
+#endif
+#if 0 //default
+ {
+ //disable drdy timing
+ Data = pci_read_config8(PCI_DEV(0, 0, 2), 0x51);
+ Data = Data & 0x7F;
+ pci_write_config8(PCI_DEV(0, 0, 2), 0x51, Data);
+ }
+#endif
+#if 0 // 2:Optimize
+ //CL :reg6x[2:0]
+ Data = pci_read_config8(MEMCTRL, 0x62);
+ CL = Data & 0x07;
+
+ //RDRPH: reg7B[6:4]
+ Data = pci_read_config8(MEMCTRL, 0x7B);
+ RDRPH = (Data & 0x70) >> 4;
+
+ //CpuFreq: F2Reg54[7:5]
+ Data = pci_read_config8(PCI_DEV(0, 0, 2), 0x54);
+ CpuFreq = (Data & 0xE0) >> 5;
+
+ //DramFreq:F3Reg90[2:0]
+ Data = pci_read_config8(MEMCTRL, 0x90);
+ DramFreq = Data & 0x07;
+
+ DelayMode = CL + RDRPH; // RDELAYMD = bit0 of (CAS Latency + RDRPH)
+ DelayMode &= 0x01;
+
+ //In 364, there is no 128 bit
+ if (DelayMode == 1) { // DelayMode 1
+ for (Index = 0; Index < PT894_RDRDY_TBL_Width; Index++)
+ ProgData[Index] =
+ PT894_64bit_DELAYMD1_RCONV0[CpuFreq][DramFreq]
+ [Index];
+ } else { // DelayMode 0
+ for (Index = 0; Index < PT894_RDRDY_TBL_Width; Index++)
+ ProgData[Index] =
+ PT894_64bit_DELAYMD0_RCONV0[CpuFreq][DramFreq]
+ [Index];
+ }
+
+ Data = ProgData[0];
+ pci_write_config8(PCI_DEV(0, 0, 2), 0x60, Data);
+
+ Data = ProgData[1];
+ pci_write_config8(PCI_DEV(0, 0, 2), 0x61, Data);
+
+ Data = ProgData[2];
+ pci_write_config8(PCI_DEV(0, 0, 2), 0x62, Data);
+
+ Data = ProgData[3];
+ pci_write_config8(PCI_DEV(0, 0, 2), 0x63, Data);
+
+ Data = ProgData[4];
+ pci_write_config8(PCI_DEV(0, 0, 2), 0x64, Data);
+
+ Data = ProgData[5];
+ pci_write_config8(PCI_DEV(0, 0, 2), 0x65, Data);
+
+ Data = ProgData[6];
+ pci_write_config8(PCI_DEV(0, 0, 2), 0x66, Data);
+
+ Data = ProgData[7];
+ pci_write_config8(PCI_DEV(0, 0, 2), 0x67, Data);
+
+ Data = pci_read_config8(PCI_DEV(0, 0, 2), 0x54);
+ Data = (Data & 0xF5) | ProgData[8];
+ pci_write_config8(PCI_DEV(0, 0, 2), 0x54, Data);
+
+ Data = pci_read_config8(PCI_DEV(0, 0, 2), 0x55);
+ Data = Data & (~0x22) | ProgData[9];
+ pci_write_config8(PCI_DEV(0, 0, 2), 0x62, Data);
+
+ //enable drdy timing
+ Data = pci_read_config8(PCI_DEV(0, 0, 2), 0x51);
+ Data = Data | 0x80;
+ pci_write_config8(PCI_DEV(0, 0, 2), 0x51, Data);
+#endif
+}
+
+
+/*This routine process the ability for North Bridge side burst functionality
+There are 3 variances that are valid:
+ 1. DIMM BL=8, chipset BL=8
+ 2. DIMM BL=4, chipset BL=4
+ 3. DIMM BL=4, chipset BL=8 (only happened on Dual channel)
+ Device 0 function 2 HOST:REG54[4] must be 1 when 128-bit mode.
+Since DIMM will be initialized in each rank individually,
+ 1.If all DIMM BL=4, DIMM will initialize BL=4 first,
+ then check dual_channel flag to enable VIA_NB2HOST_REG54[4].
+ 2.If all DIMM BL=8, DIMM will initialize BL=8 first,
+ then check dual_channel flag for re-initialize DIMM BL=4.
+ also VIA_NB2HOST_REG54[4] need to be enabled.
+Chipset_BL8==>chipset side can set burst length=8
+two register need to set
+ 1. Device 0 function 2 HOST:REG54[4]
+ 2. Device 0 function 3 DRAM:REG6C[3]
+*/
+void DRAMBurstLength(DRAM_SYS_ATTR * DramAttr)
+{
+ u8 Data, BL;
+ u8 Sockets;
+ /*SPD byte16 bit3,2 describes the burst length supported. bit3=1 support BL=8 bit2=1 support BL=4 */
+ BL = 0x0c;
+ for (Sockets = 0; Sockets < 2; Sockets++) {
+ if (DramAttr->DimmInfo[Sockets].bPresence) {
+ BL &=
+ (DramAttr->DimmInfo[Sockets].
+ SPDDataBuf[SPD_SDRAM_BURSTLENGTH]);
+ }
+ }
+
+ /*D0F3Rx6c bit3 CHA SDRAM effective burst length, for 64bit mode ranks =0 BL=4 ; =1 BL=8 */
+
+ if (BL & 0x08) /*All Assembly support BL=8 */
+ BL = 0x8; /*set bit3 */
+ else
+ BL = 0x00; /*clear bit3 */
+
+ Data = pci_read_config8(MEMCTRL, 0x6c);
+ Data = (u8) ((Data & 0xf7) | BL);
+
+#if ENABLE_CHB
+ if (DramAttr->RankNumChB > 0) {
+ BL = DramAttr->DimmInfo[2].
+ SPDDataBuf[SPD_SDRAM_BURSTLENGTH];
+ //Rx6c[1], CHB burst length
+ if (BL & 0x08) /*CHB support BL=8 */
+ BL = 0x2; /*set bit1 */
+ else
+ BL = 0x00; /*clear bit1 */
+
+ Data = (Data & 0xFD) | BL;
+ }
+#endif
+ pci_write_config8(MEMCTRL, 0x6c, Data);
+}
diff --git a/src/northbridge/via/vx800/ddr2init/vx800/Detection.c b/src/northbridge/via/vx800/ddr2init/vx800/Detection.c
new file mode 100644
index 0000000000..63fc56b845
--- /dev/null
+++ b/src/northbridge/via/vx800/ddr2init/vx800/Detection.c
@@ -0,0 +1,192 @@
+/*
+ * 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
+ */
+
+#define SMBUS_ADDR_CH_A_1 0xA0 // Dimmx
+#define SMBUS_ADDR_CH_A_2 0xA2 // Dimmx
+#define SMBUS_ADDR_CH_B_1 0xA4 // Dimmx
+#define SMBUS_ADDR_CH_B_2 0xA6 // Dimmx
+
+/*read data*/
+CB_STATUS GetSPDData(u8 Slot, u8 Length, u8 * Buf);
+
+void DRAMCmdRate(DRAM_SYS_ATTR * DramAttr);
+
+
+
+CB_STATUS GetInfoFromSPD(DRAM_SYS_ATTR * DramAttr);
+
+CB_STATUS GetSPDData(u8 Slot, u8 Length, u8 * Buf)
+{
+ // CB_STATUS Status = CB_NOT_READY;
+ u8 Val;
+ u8 i;
+
+ if (1 > Length || NULL == Buf)
+ return CB_INVALID_PARAMETER;
+
+ for (i = 0; i < Length; i++) {
+ Val = get_spd_data(ctrl.channel0[Slot], i);
+ *(Buf + i) = Val;
+ }
+ return CB_SUCCESS;
+}
+
+CB_STATUS DRAMDetect(DRAM_SYS_ATTR * DramAttr)
+{
+ CB_STATUS Status = CB_SUCCESS;
+
+ PRINT_DEBUG_MEM("Dram Detection \r");
+
+ /*Read D0F3Rx6C , detect memory type DDR1 or DDR2 */
+ // 353 supports DDR2 only
+ DramAttr->DramType = RAMTYPE_SDRAMDDR2;
+ /*get information for SPD */
+ Status = GetInfoFromSPD(DramAttr);
+ if (CB_SUCCESS == Status) {
+ /*64bit or 128Bit */
+ //
+ // if (RAMTYPE_SDRAMDDR == DramAttr->DramType)
+
+ /*select command rate */
+ DRAMCmdRate(DramAttr);
+ }
+ return Status;
+}
+
+
+// Determine 1T or 2T Command Rate:
+// To enable 1T command Rate, the system will satisfy the following 3 conditions:
+// 1. Each DRAM channel may have 1 or 2 ranks of DIMM. 3/4 ranks can not support 1T command rate
+// It's for loading issue. 1T can supports (a). only one socket with two ranks OR
+// (b). two sockets each with 1 rank.
+// 2. User wishes to enable 1T command rate mode and turn on by Setup menu
+// 3. If 1T command rate can be enabled, just set EBP bit here.
+void DRAMCmdRate(DRAM_SYS_ATTR * DramAttr)
+{
+ u8 Data;
+
+ // 5.1t/2t command rate, use the stable set
+ //offset50
+ DramAttr->CmdRate = 2;
+ Data = pci_read_config8(MEMCTRL, 0x50);
+ Data = (u8) (Data & 0xEE);
+ pci_write_config8(MEMCTRL, 0x50, Data);
+}
+
+/*get SPD data and set RANK presence map*/
+/*
+Sockets0,1 is Channel A / Sockets2,3 is Channel B
+socket0 SPD device address 0x50 / socket1 SPD device address 0x51
+socket2 SPD device address 0x52 / socket3 SPD device address 0x53
+*/
+CB_STATUS GetInfoFromSPD(DRAM_SYS_ATTR * DramAttr)
+{
+ CB_STATUS Status;
+ u8 *pSPDDataBuf;
+ u8 ModuleDataWidth;
+ u8 ChipWidth;
+ u8 RankNum;
+ u8 LoadNum;
+ u8 Sockets, i;
+ BOOLEAN bFind;
+ bFind = FALSE;
+ Status = CB_DEVICE_ERROR;
+
+ for (Sockets = 0; Sockets < MAX_SOCKETS; Sockets++) {
+ pSPDDataBuf = DramAttr->DimmInfo[Sockets].SPDDataBuf;
+ pSPDDataBuf[SPD_MEMORY_TYPE] =
+ get_spd_data(ctrl.channel0[Sockets], SPD_MEMORY_TYPE);
+ if (pSPDDataBuf[SPD_MEMORY_TYPE] == 0) {
+ Status = CB_NOT_READY;
+ } else {
+ Status =
+ GetSPDData(Sockets, SPD_DATA_SIZE,
+ pSPDDataBuf);
+ PRINT_DEBUG_MEM("SPD : \r");
+ for (i = 0; i < SPD_DATA_SIZE; i++) {
+ PRINT_DEBUG_MEM(" ");
+ PRINT_DEBUG_MEM_HEX8(pSPDDataBuf[i]);
+ }
+ }
+ if (CB_SUCCESS == Status) {
+ /*if Dram Controller detected type not same as the type got from SPD, There are ERROR */
+ if (pSPDDataBuf[SPD_MEMORY_TYPE] !=
+ DramAttr->DramType) {
+ Status = CB_DEVICE_ERROR; /*Memory int error */
+ PRINT_DEBUG_MEM
+ ("Memory Device ERROR: Dram Controller detected type != type got from SPD \r");
+ break;
+ }
+ DramAttr->DimmInfo[Sockets].bPresence = TRUE;
+ /*calculate load number (chips number) */
+ ModuleDataWidth =
+ (u8) (DramAttr->DimmInfo[Sockets].
+ SPDDataBuf[SPD_SDRAM_MOD_DATA_WIDTH +
+ 1]);
+ ModuleDataWidth = (u8) (ModuleDataWidth << 8);
+ ModuleDataWidth |=
+ (u8) (DramAttr->DimmInfo[Sockets].
+ SPDDataBuf[SPD_SDRAM_MOD_DATA_WIDTH]);
+ ChipWidth =
+ (u8) ((DramAttr->DimmInfo[Sockets].
+ SPDDataBuf[SPD_SDRAM_WIDTH]) & 0x7F);
+ LoadNum = (u8) (ModuleDataWidth / ChipWidth);
+
+ /*set the RANK map */
+ RankNum = (u8) (pSPDDataBuf[SPD_SDRAM_DIMM_RANKS] & 0x3); /*get bit0,1, the Most number of supported RANK is 2 */
+ if (RAMTYPE_SDRAMDDR2 == DramAttr->DramType)
+ RankNum++; /*for DDR bit[0,1] 01->1 RANK 10->2 RANK; for DDR2 bit[0,1] = 00 -> 1 RANK 01 -> 2 RANK */
+ if (RankNum != 2 && RankNum != 1) { /*every DIMM have 1 or 2 ranks */
+ Status = CB_DEVICE_ERROR;
+ PRINT_DEBUG_MEM
+ ("Memory Device ERROR: the number of RANK not support!\r");
+ break;
+ }
+
+ if (Sockets < 2) { /*sockets0,1 is channel A */
+ DramAttr->RankNumChA =
+ (u8) (DramAttr->RankNumChA + RankNum);
+ DramAttr->DimmNumChA++;
+ DramAttr->LoadNumChA =
+ (u8) (DramAttr->LoadNumChA * LoadNum *
+ RankNum);
+ } else { /*sockets2,3 is channel B */
+
+ DramAttr->RankNumChB =
+ (u8) (DramAttr->RankNumChB + RankNum);
+ DramAttr->DimmNumChB++;
+ DramAttr->LoadNumChB =
+ (u8) (DramAttr->LoadNumChB * LoadNum *
+ RankNum);;
+ }
+ RankNum |= 1; /*set rank map */
+ DramAttr->RankPresentMap |=
+ (RankNum << (Sockets * 2));
+ bFind = TRUE;
+ }
+ }
+ PRINT_DEBUG_MEM("Rank Present Map:");
+ PRINT_DEBUG_MEM_HEX8(DramAttr->RankPresentMap);
+ PRINT_DEBUG_MEM("\r");
+
+ if (bFind)
+ Status = CB_SUCCESS;
+
+ return Status;
+}
diff --git a/src/northbridge/via/vx800/ddr2init/vx800/DevInit.c b/src/northbridge/via/vx800/ddr2init/vx800/DevInit.c
new file mode 100644
index 0000000000..6a6ab22dce
--- /dev/null
+++ b/src/northbridge/via/vx800/ddr2init/vx800/DevInit.c
@@ -0,0 +1,1318 @@
+/*
+ * 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();
+/*===================================================================
+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] = {
+ //Register 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;
+ u8 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 Controllor 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
+BOOLEAN ChkForExistLowBank()
+{
+ 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 InitDDR2CHC(DRAM_SYS_ATTR * DramAttr);
+void InitDDR2CHB(DRAM_SYS_ATTR * DramAttr);
+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;
+ u8 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 the 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;
+ u8 Reg6BVal;
+ u8 Idx, CL, BL, Twr;
+ u32 AccessAddr;
+ u8 DimmNum;
+
+ // step2.
+ //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);
+
+ // step4.
+ //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 DrivingSetting.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);
+
+ // Step12.
+ //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;
+ u8 Idx, CL, Twr;
+ u32 AccessAddr;
+ CB_STATUS Status;
+
+ // step3.
+ //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);
+
+ //step10. MRS enable
+ Data = pci_read_config8(MEMCTRL, 0xdb);
+ Data &= 0xE3;
+ Data |= 0x1C;
+ pci_write_config8(MEMCTRL, 0xdb, Data);
+
+
+ //step11. EMRS DLL enable and Disable DQS
+ Data = 0x40;
+ pci_write_config8(MEMCTRL, 0xf8, Data);
+
+ Data = 0x24;
+ pci_write_config8(MEMCTRL, 0xf9, Data);
+
+ //step12. 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);
+
+ //step13. 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);
+
+ //step15. 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);
+
+ //step16. 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);
+
+ // step17. 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);
+
+ //step18. 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()
+{
+ 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;
+}
diff --git a/src/northbridge/via/vx800/ddr2init/vx800/DrivingSetting.c b/src/northbridge/via/vx800/ddr2init/vx800/DrivingSetting.c
new file mode 100644
index 0000000000..3bdfdf391f
--- /dev/null
+++ b/src/northbridge/via/vx800/ddr2init/vx800/DrivingSetting.c
@@ -0,0 +1,396 @@
+/*
+ * 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
+ */
+
+/*
+ Driving setting: ODT/DQS/DQ/CS/MAA/MAB/DCLK
+ */
+
+void DrivingODT(DRAM_SYS_ATTR * DramAttr);
+
+void DrivingDQS(DRAM_SYS_ATTR * DramAttr);
+
+void DrivingDQ(DRAM_SYS_ATTR * DramAttr);
+
+void DrivingCS(DRAM_SYS_ATTR * DramAttr);
+
+void DrivingMA(DRAM_SYS_ATTR * DramAttr);
+
+void DrivingDCLK(DRAM_SYS_ATTR * DramAttr);
+
+/* DRAM Driving Adjustment*/
+void DRAMDriving(DRAM_SYS_ATTR * DramAttr)
+{
+ PRINT_DEBUG_MEM("set ODT!\r");
+ DrivingODT(DramAttr);
+
+ PRINT_DEBUG_MEM("set DQS!\r");
+ DrivingDQS(DramAttr);
+
+ PRINT_DEBUG_MEM(("set DQ!\r"));
+ DrivingDQ(DramAttr);
+
+ PRINT_DEBUG_MEM("set CS!\r");
+ DrivingCS(DramAttr);
+
+ PRINT_DEBUG_MEM("set MAA!\r");
+ DrivingMA(DramAttr);
+
+ PRINT_DEBUG_MEM("set DCLK!\r");
+ DrivingDCLK(DramAttr);
+}
+
+
+/*
+ODT Control for DQ/DQS/CKE/SCMD/DCLKO in ChA & ChB
+which include driving enable/range and strong/weak selection
+
+Processing: According to DRAM frequency to ODT control bits.
+ Because function enable bit must be the last one to be set.
+ So the register VIA_NB3DRAM_REGD4 and VIA_NB3DRAM_REGD3 should be
+ the last register to be programmed.
+*/
+//-------------------------------------------------------------------------------
+// ODT Lookup Table
+//-------------------------------------------------------------------------------
+#define Rank0_ODT 0
+#define Rank1_ODT 1
+#define Rank2_ODT 2
+#define Rank3_ODT 3
+#define NA_ODT 0
+#define NB_ODT_75ohm 0
+#define NB_ODT_150ohm 1
+
+#define DDR2_ODT_75ohm 0x20
+#define DDR2_ODT_150ohm 0x40
+
+// Setting of ODT Lookup TBL
+// RankMAP , Rank 3 Rank 2 Rank 1 Rank 0 , DRAM & NB ODT setting
+// db 0000b , Reserved
+#define ODTLookup_Tbl_count 8
+static const u8 ODTLookup_TBL[ODTLookup_Tbl_count][3] = {
+ // 0001b
+ {0x01,
+ (Rank3_ODT << 6) + (Rank2_ODT << 4) + (Rank1_ODT << 2) +
+ Rank0_ODT, DDR2_ODT_150ohm + NB_ODT_75ohm},
+ // 0010b , Reserved
+ // 0011b
+ {0x03,
+ (Rank3_ODT << 6) + (Rank2_ODT << 4) + (Rank0_ODT << 2) +
+ Rank1_ODT, DDR2_ODT_150ohm + NB_ODT_75ohm},
+ // 0100b
+ {0x04,
+ (Rank3_ODT << 6) + (Rank2_ODT << 4) + (Rank1_ODT << 2) +
+ Rank0_ODT, DDR2_ODT_150ohm + NB_ODT_75ohm},
+ // 0101b
+ {0x05,
+ (Rank3_ODT << 6) + (Rank0_ODT << 4) + (Rank1_ODT << 2) +
+ Rank2_ODT, DDR2_ODT_75ohm + NB_ODT_150ohm},
+ // 0110b , Reserved
+ // 0111b
+ {0x07,
+ (Rank3_ODT << 6) + (Rank0_ODT << 4) + (Rank2_ODT << 2) +
+ Rank2_ODT, DDR2_ODT_75ohm + NB_ODT_150ohm},
+ // 1000b , Reserved
+ // 1001b , Reserved
+ // 1010b , Reserved
+ // 1011b , Reserved
+ // 1100b
+ {0x0c,
+ (Rank2_ODT << 6) + (Rank3_ODT << 4) + (Rank1_ODT << 2) +
+ Rank0_ODT, DDR2_ODT_150ohm + NB_ODT_75ohm},
+ // 1101b
+ {0x0d,
+ (Rank0_ODT << 6) + (Rank0_ODT << 4) + (Rank1_ODT << 2) +
+ Rank2_ODT, DDR2_ODT_75ohm + NB_ODT_150ohm},
+ // 1110b , Reserved
+ // 1111b
+ {0x0f,
+ (Rank0_ODT << 6) + (Rank0_ODT << 4) + (Rank2_ODT << 2) +
+ Rank2_ODT, DDR2_ODT_75ohm + NB_ODT_150ohm}
+};
+
+#define ODT_Table_Width_DDR2 4
+// RxD6 RxD3
+static const u8 ODT_Control_DDR2[ODT_Table_Width_DDR2] = { 0xFC, 0x01 };
+
+void DrivingODT(DRAM_SYS_ATTR * DramAttr)
+{
+ u8 Data;
+ u8 i;
+ BOOLEAN bFound;
+
+ pci_write_config8(MEMCTRL, 0xD0, 0x88);
+
+ Data = ODT_Control_DDR2[0];
+ pci_write_config8(MEMCTRL, 0xd6, Data);
+
+ Data = ODT_Control_DDR2[1];
+ pci_write_config8(MEMCTRL, 0xd3, Data);
+
+ Data = pci_read_config8(MEMCTRL, 0x9e);
+ //set MD turn_around wait state
+ Data &= 0xCF; /*clear bit4,5 */
+ if (DIMMFREQ_400 == DramAttr->DramFreq)
+ Data |= 0x0;
+ else if (DIMMFREQ_533 == DramAttr->DramFreq)
+ Data |= 0x10;
+ else if (DIMMFREQ_667 == DramAttr->DramFreq)
+ Data |= 0x20;
+ else if (DIMMFREQ_800 == DramAttr->DramFreq)
+ Data |= 0x20;
+ else
+ Data |= 0;
+ pci_write_config8(MEMCTRL, 0x9e, Data);
+
+
+ if (DIMMFREQ_400 == DramAttr->DramFreq)
+ Data = 0x0;
+ else if (DIMMFREQ_533 == DramAttr->DramFreq)
+ Data = 0x11;
+ else if (DIMMFREQ_667 == DramAttr->DramFreq)
+ Data = 0x11;
+ else if (DIMMFREQ_800 == DramAttr->DramFreq)
+ Data = 0x11;
+ else
+ Data = 0;
+ pci_write_config8(MEMCTRL, 0x9f, Data);
+
+
+ /*channel A ODT select */
+ if (DramAttr->DimmNumChA > 0) {
+ Data = pci_read_config8(MEMCTRL, 0xd5);
+ Data &= 0x5F; /*clear bit7,5 */
+ if (DramAttr->RankNumChA > 2)
+ Data |= 0xA0; /*if rank number > 2 (3or4), set bit7,5 */
+ else
+ Data |= 0x00; /*if rank number is 1or2, clear bit5 */
+ pci_write_config8(MEMCTRL, 0xd5, Data);
+
+ Data = pci_read_config8(MEMCTRL, 0xd7);
+ Data &= 0xEF; /*clear bit7 */
+ if (DramAttr->RankNumChA > 2)
+ Data |= 0x80; /*if rank number > 2 (3or4), set bit7 */
+ else
+ Data |= 0x00; /*if rank number is 1or2, clear bit7 */
+ pci_write_config8(MEMCTRL, 0xd7, Data);
+
+
+ /*channel A */
+ Data = pci_read_config8(MEMCTRL, 0xd5);
+ Data &= 0xF3; //bit2,3
+ if (DramAttr->DimmNumChA == 2) /*2 Dimm, 3or4 Ranks */
+ Data |= 0x00;
+ else if (DramAttr->DimmNumChA == 1)
+ Data |= 0x04;
+ pci_write_config8(MEMCTRL, 0xd5, Data);
+
+ if ((DramAttr->RankPresentMap & 0x0F) != 0) { /*channel A */
+ // MAA ODT Lookup Table
+ bFound = FALSE;
+ for (i = 0; i < ODTLookup_Tbl_count; i++) {
+ if ((DramAttr->RankPresentMap & 0x0F) ==
+ ODTLookup_TBL[i][0]) {
+ Data = ODTLookup_TBL[i][1];
+ bFound = TRUE;
+ }
+ }
+ if (!bFound) { /*set default value */
+ Data =
+ ODTLookup_TBL[ODTLookup_Tbl_count -
+ 1][1];
+ }
+ pci_write_config8(MEMCTRL, 0x9c, Data);
+
+
+ //set CHA MD ODT control State Dynamic-on
+ Data = pci_read_config8(MEMCTRL, 0xD4);
+ Data &= 0xC9;
+ Data |= 0x30;
+ pci_write_config8(MEMCTRL, 0xD4, Data);
+
+ Data = pci_read_config8(MEMCTRL, 0x9e);
+ Data |= 0x01;
+ pci_write_config8(MEMCTRL, 0x9e, Data);
+ }
+
+ }
+ /*channel B */
+ if (1 == ENABLE_CHC) {
+ //CHB has not auto compensation mode ,so must set it manual,or else CHB initialization will not successful
+ // Data =0x88;
+ //pci_write_config8(MEMCTRL, 0xd0, Data);
+
+ Data = pci_read_config8(MEMCTRL, 0xd5);
+ Data &= 0xAF;
+ if (DramAttr->RankNumChB > 2) /*rank number 3 or 4 */
+ Data |= 0x50;
+ else
+ Data |= 0x00;
+ pci_write_config8(MEMCTRL, 0xd5, Data);
+
+ Data = pci_read_config8(MEMCTRL, 0xd7);
+ Data &= 0xBF; /*clear bit6 */
+ if (DramAttr->RankNumChB > 2)
+ Data |= 0x40; /*if rank number > 2 (3or4), set bit7 */
+ else
+ Data |= 0x00; /*if rank number is 1or2, clear bit7 */
+ pci_write_config8(MEMCTRL, 0xd7, Data);
+
+
+ Data = pci_read_config8(MEMCTRL, 0xd5);
+ Data &= 0xFC;
+ if (DramAttr->DimmNumChB == 2) /*2 Dimm, 3or4 Ranks */
+ Data |= 0x00; // 2 dimm RxD5[2,0]=0,0b
+ else if (DramAttr->DimmNumChB == 1)
+ Data |= 0x01; // 1 dimm RxD5[2,0]=1,1b
+ pci_write_config8(MEMCTRL, 0xd5, Data);
+
+ //set CHB MD ODT control State Dynamic-on
+ Data = pci_read_config8(MEMCTRL, 0xD4);
+ Data &= 0xF6;
+ Data |= 0x08;
+ pci_write_config8(MEMCTRL, 0xD4, Data);
+
+
+ //enable CHB differential DQS input
+ Data = pci_read_config8(MEMCTRL, 0x9E);
+ Data |= 0x02;
+ pci_write_config8(MEMCTRL, 0x9E, Data);
+ }
+ //enable ODT Control
+ Data = pci_read_config8(MEMCTRL, 0x9e);
+ Data |= 0x80;
+ pci_write_config8(MEMCTRL, 0x9e, Data);
+}
+
+void DrivingDQS(DRAM_SYS_ATTR * DramAttr)
+{
+ u8 Data;
+
+ /*channel A */
+ if (DramAttr->RankNumChA > 0) {
+ Data = DDR2_DQSA_Driving_Table[DramAttr->RankNumChA - 1];
+ pci_write_config8(MEMCTRL, 0xe0, Data);
+ }
+
+ /*channel B */
+ if (1 == ENABLE_CHC) {
+ Data = DDR2_DQSB_Driving_Table[DramAttr->RankNumChB - 1];
+ pci_write_config8(MEMCTRL, 0xe1, Data);
+ }
+
+}
+
+void DrivingDQ(DRAM_SYS_ATTR * DramAttr)
+{
+ u8 Data;
+
+ /*channel A */
+ if (DramAttr->RankNumChA > 0) {
+ Data = DDR2_DQA_Driving_Table[DramAttr->RankNumChA - 1];
+ pci_write_config8(MEMCTRL, 0xe2, Data);
+
+ }
+ /*channel B */
+ if (1 == ENABLE_CHC) {
+ Data = DDR2_DQB_Driving_Table[DramAttr->RankNumChB - 1];
+ pci_write_config8(MEMCTRL, 0xe3, Data);
+ }
+}
+
+void DrivingCS(DRAM_SYS_ATTR * DramAttr)
+{
+ u8 Data;
+ /*Channel A */
+ if (DramAttr->RankNumChA > 0) {
+ Data = DDR2_CSA_Driving_Table_x8[DramAttr->RankNumChA - 1];
+ pci_write_config8(MEMCTRL, 0xe4, Data);
+ }
+ /*channel B */
+ if (1 == ENABLE_CHC) {
+ Data = DDR2_CSB_Driving_Table_x8[DramAttr->RankNumChB - 1];
+ pci_write_config8(MEMCTRL, 0xe5, Data);
+ }
+}
+
+void DrivingMA(DRAM_SYS_ATTR * DramAttr)
+{
+ u8 Data;
+ u8 i, FreqId;
+
+ if (DramAttr->RankNumChA > 0) {
+ if (DIMMFREQ_400 == DramAttr->DramFreq)
+ FreqId = 1;
+ else if (DIMMFREQ_533 == DramAttr->DramFreq)
+ FreqId = 2;
+ else if (DIMMFREQ_667 == DramAttr->DramFreq)
+ FreqId = 3;
+ else if (DIMMFREQ_800 == DramAttr->DramFreq)
+ FreqId = 4;
+ else
+ FreqId = 1;
+ for (i = 0; i < MA_Table; i++) {
+ if (DramAttr->LoadNumChA <=
+ DDR2_MAA_Driving_Table[i][0]) {
+ Data = DDR2_MAA_Driving_Table[i][FreqId];
+ break;
+ }
+ }
+ pci_write_config8(MEMCTRL, 0xe8, Data);
+ }
+ if (1 == ENABLE_CHC) {
+ for (i = 0; i < MA_Table; i++) {
+ if (DramAttr->LoadNumChA <=
+ DDR2_MAB_Driving_Table[i][0]) {
+ Data = DDR2_MAB_Driving_Table[i][1];
+ break;
+ }
+ }
+ pci_write_config8(MEMCTRL, 0xe9, Data);
+ }
+}
+
+void DrivingDCLK(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 = 4;
+ else
+ FreqId = 0;
+
+ /*channel A */
+ if (DramAttr->RankNumChA > 0) {
+ Data = DDR2_DCLKA_Driving_Table[FreqId];
+ pci_write_config8(MEMCTRL, 0xe6, Data);
+ }
+ /*channel B */
+ if (1 == ENABLE_CHC) {
+ Data = DDR2_DCLKB_Driving_Table[FreqId];
+ pci_write_config8(MEMCTRL, 0xe7, Data);
+ }
+
+}
diff --git a/src/northbridge/via/vx800/ddr2init/vx800/FinalSetting.c b/src/northbridge/via/vx800/ddr2init/vx800/FinalSetting.c
new file mode 100644
index 0000000000..165c887d8a
--- /dev/null
+++ b/src/northbridge/via/vx800/ddr2init/vx800/FinalSetting.c
@@ -0,0 +1,129 @@
+/*
+ * 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
+ */
+
+static const u8 RefreshCounter[7][2] = {
+ //Non_256Mbit, 256Mbit
+ {0xCA, 0xA8}, // DRAM400
+ {0xCA, 0xA8}, // DRAM333
+ {0xCA, 0x86}, // DRAM266
+ {0xCA, 0x65}, // DRAM200
+ {0xA8, 0x54}, // DRAM166
+ {0x86, 0x43}, // DRAM133
+ {0x65, 0x32} // DRAM100
+};
+
+void DRAMRefreshCounter(DRAM_SYS_ATTR * DramAttr)
+{
+ u8 Data;
+ u8 Freq = 5, i, Dram_256_Mb;
+ if (DramAttr->DramFreq == DIMMFREQ_800)
+ Freq = 0;
+ else if (DramAttr->DramFreq == DIMMFREQ_667)
+ Freq = 1;
+ else if (DramAttr->DramFreq == DIMMFREQ_533)
+ Freq = 2;
+ else if (DramAttr->DramFreq == DIMMFREQ_400)
+ Freq = 3;
+ else if (DramAttr->DramFreq == DIMMFREQ_333)
+ Freq = 4;
+ else if (DramAttr->DramFreq == DIMMFREQ_266)
+ Freq = 5;
+ else if (DramAttr->DramFreq == DIMMFREQ_200)
+ Freq = 6;
+ else
+ Freq = 6;
+
+ Dram_256_Mb = 0;
+ for (i = 0; i < MAX_SOCKETS; i++) {
+ if (DramAttr->DimmInfo[i].SPDDataBuf[SPD_SDRAM_ROW_ADDR] ==
+ 13) {
+ Dram_256_Mb = 1;
+ break;
+ }
+ }
+
+ Data = RefreshCounter[Freq][Dram_256_Mb];
+
+ pci_write_config8(MEMCTRL, 0x6a, Data);
+}
+
+
+/*===================================================================
+Function : DRAMRegFinalValue()
+Precondition :
+Input :
+ DramAttr: pointer point to DRAM_SYS_ATTR which consist the DDR and Dimm information
+ in MotherBoard
+Output : Void
+Purpose : Chipset Performance UP and other setting after DRAM Sizing
+ Turn on register directly to promote performance
+===================================================================*/
+
+//--------------------------------------------------------------------------
+// register AND OR
+//--------------------------------------------------------------------------
+#define DRAM_table_item 9
+static const u8 DRAM_table[DRAM_table_item][3] = {
+ {0x60, 0xff, 0xD0},
+ {0x66, 0xcf, 0x80}, // DRAMC queue > 2
+ {0x69, 0xff, 0x07}, // Enable multiple page
+ {0x95, 0x00, 0x0D},
+ {0x96, 0x0F, 0xA0},
+ {0xFB, 0x00, 0x3E},
+ {0xFD, 0x00, 0xA9},
+ {0xFE, 0x00, 0x0f},
+ {0xFF, 0x00, 0x3D}
+};
+
+#define PM_table_item 5
+static const u8 PM_table[PM_table_item][3] = {
+ {0xA0, 0x0F, 0xF0},
+ {0xA1, 0x1F, 0xE0},
+ {0xA2, 0x00, 0xFE},
+ {0xA3, 0x7F, 0x80},
+ {0xA5, 0x7E, 0x81},
+};
+
+void DRAMRegFinalValue(DRAM_SYS_ATTR * DramAttr)
+{
+ u8 Data;
+ u8 i;
+
+ for (i = 0; i < DRAM_table_item; i++) {
+ Data = pci_read_config8(MEMCTRL, DRAM_table[i][0]);
+ Data = (u8) ((Data & DRAM_table[i][1]) | DRAM_table[i][2]);
+ pci_write_config8(MEMCTRL, DRAM_table[i][0], Data);
+ }
+
+ //enable dram By-Rank self refresh
+ Data = pci_read_config8(MEMCTRL, 0x96);
+ Data &= 0xF0;
+ for (i = 0x01; i < 0x10; i = i << 1) {
+ if ((DramAttr->RankPresentMap & i) != 0x00)
+ Data |= i;
+ }
+ pci_write_config8(MEMCTRL, 0x96, Data);
+
+ for (i = 0; i < PM_table_item; i++) {
+ Data = pci_read_config8(PCI_DEV(0, 0, 4), PM_table[i][0]);
+ Data = (u8) ((Data & PM_table[i][1]) | PM_table[i][2]);
+ pci_write_config8(PCI_DEV(0, 0, 4), PM_table[i][0], Data);
+ }
+
+}
diff --git a/src/northbridge/via/vx800/ddr2init/vx800/FreqSetting.c b/src/northbridge/via/vx800/ddr2init/vx800/FreqSetting.c
new file mode 100644
index 0000000000..ed4184ec77
--- /dev/null
+++ b/src/northbridge/via/vx800/ddr2init/vx800/FreqSetting.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");
+}
diff --git a/src/northbridge/via/vx800/ddr2init/vx800/RankMap.c b/src/northbridge/via/vx800/ddr2init/vx800/RankMap.c
new file mode 100644
index 0000000000..f86a3648d3
--- /dev/null
+++ b/src/northbridge/via/vx800/ddr2init/vx800/RankMap.c
@@ -0,0 +1,363 @@
+/*
+ * 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
+ */
+
+extern void DRAMSetVRNum(DRAM_SYS_ATTR * DramAttr,
+ u8 PhyRank, u8 VirRank, BOOLEAN Enable);
+
+extern 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 DRAMClearEndingAddress(DRAM_SYS_ATTR * DramAttr);
+
+void DRAMSizingEachRank(DRAM_SYS_ATTR * DramAttr);
+
+BOOLEAN DoDynamicSizing1XM(DRAM_SYS_ATTR * DramAttr,
+ u8 * nRA, u8 * nCA, u8 * nBS, u8 PhyRank);
+
+void DRAMSetRankMAType(DRAM_SYS_ATTR * DramAttr);
+
+void DRAMSetEndingAddress(DRAM_SYS_ATTR * DramAttr);
+
+void DRAMPRToVRMapping(DRAM_SYS_ATTR * DramAttr);
+
+/*===================================================================
+Function : DRAMBankInterleave()
+Precondition :
+Input :
+ DramAttr: pointer point to DRAMSYSATTR which consist the DDR and Dimm information in MotherBoard
+Output : Void
+Purpose : STEP 13 Set Bank Interleave VIANB3DRAMREG69[7:6] 00:No Interleave 01:2 Bank 10:4 Bank 11:8 Bank
+ Scan all DIMMs on board to find out the lowest Bank Interleave among these DIMMs and set register.
+===================================================================*/
+void DRAMBankInterleave(DRAM_SYS_ATTR * DramAttr)
+{
+ u8 Data, SpdBAData;
+ DIMM_INFO *CurrentDimminfo;
+ u8 Bank = 3, Shift, RankNO, Count;
+ Shift = 1;
+ for (RankNO = 0; RankNO < 4; RankNO += 2) //all_even 0 RankNO 4 6
+ {
+ if ((DramAttr->RankPresentMap & Shift) != 0) {
+ CurrentDimminfo = &(DramAttr->DimmInfo[RankNO >> 1]); //this Rank in a dimm
+ SpdBAData =
+ (u8) (CurrentDimminfo->
+ SPDDataBuf[SPD_SDRAM_NO_OF_BANKS]);
+ if (SpdBAData == 4)
+ Count = 2;
+ else if (SpdBAData == 8)
+ Count = 3;
+ else
+ Count = 0;
+ if (Count < Bank)
+ Bank = Count;
+ }
+ Shift <<= 2;
+ }
+
+ Data = pci_read_config8(MEMCTRL, 0x69);
+ Data &= ~0xc0;
+ Data |= (Bank << 6);
+ pci_write_config8(MEMCTRL, 0x69, Data);
+
+
+ if (DramAttr->DimmNumChB > 0) {
+ CurrentDimminfo = &(DramAttr->DimmInfo[3]); //this Rank in a dimm
+ SpdBAData =
+ (u8) (CurrentDimminfo->
+ SPDDataBuf[SPD_SDRAM_NO_OF_BANKS]);
+ if (SpdBAData == 4)
+ Bank = 2;
+ else if (SpdBAData == 2)
+ Bank = 1;
+ else
+ Bank = 0;
+ pci_write_config8(MEMCTRL, 0x87, Bank);
+ }
+}
+
+/*===================================================================
+Function : DRAMSizingMATypeM()
+Precondition :
+Input :
+ DramAttr: pointer point to DRAMSYSATTR which consist the DDR and Dimm information in MotherBoard
+Output : Void
+ Purpose : STEP 14 1 DRAM Sizing 2 Fill MA type 3 Prank to vrankMapping
+===================================================================*/
+void DRAMSizingMATypeM(DRAM_SYS_ATTR * DramAttr)
+{
+ DRAMClearEndingAddress(DramAttr);
+ DRAMSizingEachRank(DramAttr);
+ //DRAMReInitDIMMBL (DramAttr);
+ DRAMSetRankMAType(DramAttr);
+ DRAMSetEndingAddress(DramAttr);
+ DRAMPRToVRMapping(DramAttr);
+}
+
+/*===================================================================
+Function : DRAMClearEndingAddress()
+Precondition :
+Input :
+ DramAttr: pointer point to DRAMSYSATTR which consist the DDR and Dimm information in MotherBoard
+Output : Void
+Purpose : clear Ending and Start adress from 0x40-4f to zero
+===================================================================*/
+void DRAMClearEndingAddress(DRAM_SYS_ATTR * DramAttr)
+{
+ u8 Data, Reg;
+ Data = 0;
+ for (Reg = 0x40; Reg <= 0x4f; Reg++) {
+ pci_write_config8(MEMCTRL, Reg, Data);
+ }
+}
+
+/*===================================================================
+Function : DRAMSizingEachRank()
+Precondition :
+Input :
+ DramAttr: pointer point to DRAMSYSATTR which consist the DDR and Dimm information in MotherBoard
+Output : Void
+Purpose : Sizing each Rank invidually, by number of rows column banks pins, be care about 128bit
+===================================================================*/
+void DRAMSizingEachRank(DRAM_SYS_ATTR * DramAttr)
+{
+ u8 Slot, RankIndex, Rows, Columns, Banks;
+ u32 Size;
+ BOOLEAN HasThreeBitBA;
+ u8 Data;
+ u32 Address;
+
+ HasThreeBitBA = FALSE;
+ for (Slot = 0; Slot < 2; Slot++) {
+ if (!DramAttr->DimmInfo[Slot].bPresence)
+ continue;
+ Rows =
+ DramAttr->DimmInfo[Slot].
+ SPDDataBuf[SPD_SDRAM_ROW_ADDR];
+ Columns =
+ DramAttr->DimmInfo[Slot].
+ SPDDataBuf[SPD_SDRAM_COL_ADDR];
+ Banks = DramAttr->DimmInfo[Slot].SPDDataBuf[SPD_SDRAM_NO_OF_BANKS]; //this is Bank number not Bank address bit
+ if (Banks == 4)
+ Banks = 2;
+ else if (Banks == 8)
+ Banks = 3;
+ else
+ Banks = 0;
+ Size = (u32) (1 << (Rows + Columns + Banks + 3));
+ RankIndex = 2 * Slot;
+ DramAttr->RankSize[RankIndex] = Size;
+ //if this module have two ranks
+ if ((DramAttr->DimmInfo[Slot].
+ SPDDataBuf[SPD_SDRAM_DIMM_RANKS] & 0x07) == 0x01) {
+ RankIndex++;
+ DramAttr->RankSize[RankIndex] = Size;
+ }
+
+ PRINT_DEBUG_MEM("rows: ");
+ PRINT_DEBUG_MEM_HEX8(Rows);
+ PRINT_DEBUG_MEM(", columns:");
+ PRINT_DEBUG_MEM_HEX8(Columns);
+ PRINT_DEBUG_MEM(", banks:");
+ PRINT_DEBUG_MEM_HEX8(Banks);
+ PRINT_DEBUG_MEM("\r");
+
+ if (Banks == 3)
+ HasThreeBitBA = TRUE;
+ }
+
+ //must set BA2 enable if any 8-bank device exists
+ if (HasThreeBitBA) {
+ Data = pci_read_config8(MEMCTRL, 0x53);
+ Data |= 0x80;
+ pci_write_config8(MEMCTRL, 0x53, Data);
+ }
+#if 1
+ for (RankIndex = 0; DramAttr->RankSize[RankIndex] != 0;
+ RankIndex++) {
+ PRINT_DEBUG_MEM("Rank:");
+ PRINT_DEBUG_MEM_HEX8(RankIndex);
+ PRINT_DEBUG_MEM(", Size:");
+ PRINT_DEBUG_MEM_HEX32(DramAttr->RankSize[RankIndex] >> 20);
+ PRINT_DEBUG_MEM("\r");
+ }
+#endif
+}
+
+/*===================================================================
+Function : DRAMSetRankMAType()
+Precondition :
+Input :
+ DramAttr: pointer point to DRAMSYSATTR which consist the DDR and Dimm information in MotherBoard
+Output : Void
+Purpose : set the matype Reg by MAMapTypeTbl, which the rule can be found in memoryinit
+===================================================================*/
+void DRAMSetRankMAType(DRAM_SYS_ATTR * DramAttr)
+{
+ u8 SlotNum, Data, j, Reg, or, and;
+ u8 ShiftBits[] = { 5, 1, 5, 1 }; /* Rank 0/1 MA Map Type is 7:5, Rank 2/3 MA Map Type is 3:1. See Fun3Rx50. */
+ u8 MAMapTypeTbl[] = { /* Table 12 of P4M800 Pro DataSheet. */
+ 2, 9, 0, /* Bank Address Bits, Column Address Bits, Rank MA Map Type */
+ 2, 10, 1,
+ 2, 11, 2,
+ 2, 12, 3,
+ 3, 10, 5,
+ 3, 11, 6,
+ 3, 12, 7,
+ 0, 0, 0
+ };
+ Data = pci_read_config8(MEMCTRL, 0x50);
+ Data &= 0x1;
+ pci_write_config8(MEMCTRL, 0x50, Data);
+ // disable MA32/16 MA33/17 swap in memory init it has this Reg fill
+ Data = pci_read_config8(MEMCTRL, 0x6b);
+ Data &= ~0x08;
+ pci_write_config8(MEMCTRL, 0x6b, Data);
+
+ Data = 0x00;
+ for (SlotNum = 0; SlotNum < MAX_DIMMS; SlotNum++) {
+ if (DramAttr->DimmInfo[SlotNum].bPresence) {
+ for (j = 0; MAMapTypeTbl[j] != 0; j += 3) {
+ if ((1 << MAMapTypeTbl[j]) ==
+ DramAttr->DimmInfo[SlotNum].
+ SPDDataBuf[SPD_SDRAM_NO_OF_BANKS]
+ && MAMapTypeTbl[j + 1] ==
+ DramAttr->DimmInfo[SlotNum].
+ SPDDataBuf[SPD_SDRAM_COL_ADDR]) {
+ break;
+ }
+ }
+ if (0 == MAMapTypeTbl[j]) {
+ PRINT_DEBUG_MEM
+ ("UNSUPPORTED Bank, Row and Column Addr Bits!\r");
+ return;
+ }
+ or = MAMapTypeTbl[j + 2] << ShiftBits[SlotNum];
+ if (DramAttr->CmdRate == 1)
+ or |= 0x01 << (ShiftBits[SlotNum] - 1);
+
+ Reg = SlotNum / 2;
+ if ((SlotNum & 0x01) == 0x01) {
+ and = 0xf1; // BUGBUG: it should be 0xf0
+ } else {
+ and = 0x1f; // BUGBUG: it should be 0x0f
+ }
+ Data = pci_read_config8(MEMCTRL, 0x50 + Reg);
+ Data &= and;
+ Data |= or;
+ pci_write_config8(MEMCTRL, 0x50 + Reg, Data);
+ }
+ }
+ //may have some Reg filling at add 3-52 11 and 3-53 in his function
+}
+
+/*===================================================================
+Function : DRAMSetEndingAddress()
+Precondition :
+Input :
+ DramAttr: pointer point to DRAMSYSATTR which consist the DDR and Dimm information in MotherBoard
+Output : Void
+Purpose : realize the Vrank 40...Reg (Start and Ending Regs). Vrank have same order with phy Rank, Size is actual Size
+===================================================================*/
+void DRAMSetEndingAddress(DRAM_SYS_ATTR * DramAttr)
+{
+ u8 Shift = 1, Data, RankNO, Size, Start = 0, End = 0, Vrank;
+ for (RankNO = 0; RankNO < 4; RankNO++) {
+ if ((DramAttr->RankPresentMap & Shift) != 0) {
+ Size = (u8) (DramAttr->RankSize[RankNO] >> 26); // current Size in the unit of 64M
+ if (Size != 0) {
+
+ End = End + Size; // calculate current ending address, add the current Size to ending
+ Vrank = RankNO; // get virtual Rank
+ Data = End; // set begin/End address register to correspondig virtual Rank #
+ pci_write_config8(MEMCTRL, 0x40 + Vrank,
+ Data);
+ Data = Start;
+ pci_write_config8(MEMCTRL, 0x48 + Vrank,
+ Data);
+ PRINT_DEBUG_MEM("Rank: ");
+ PRINT_DEBUG_MEM_HEX8(Vrank);
+ PRINT_DEBUG_MEM(", Start:");
+ PRINT_DEBUG_MEM_HEX8(Start);
+ PRINT_DEBUG_MEM(", End:");
+ PRINT_DEBUG_MEM_HEX8(End);
+ PRINT_DEBUG_MEM("\r");
+
+ Start = End;
+ }
+ }
+ Shift <<= 1;
+ }
+
+ if (DramAttr->RankNumChB > 0) {
+ //this is a bug,fixed is to 2,so the max LL size is 128M
+ Data = 0x02;
+ pci_write_config8(MEMCTRL, 0x44, Data);
+ }
+ Data = End * 4;
+ pci_write_config8(PCI_DEV(0, 17, 7), 0x60, Data);
+ // We should directly write to south Bridge, not in north bridge
+ // program LOW TOP Address
+ Data = pci_read_config8(MEMCTRL, 0x88);
+ pci_write_config8(MEMCTRL, 0x85, Data);
+
+ // also program vlink mirror
+ // We should directly write to south Bridge, not in north bridge
+ pci_write_config8(PCI_DEV(0, 17, 7), 0xe5, Data);
+}
+
+/*===================================================================
+Function : DRAMPRToVRMapping()
+Precondition :
+Input :
+ DramAttr: pointer point to DRAMSYSATTR which consist the DDR and Dimm information in MotherBoard
+Output : Void
+Purpose : set the Vrank-prank map with the same order
+===================================================================*/
+void DRAMPRToVRMapping(DRAM_SYS_ATTR * DramAttr)
+{
+ u8 Shift, Data, and, or, DimmNO = 0, PhyRankNO, Reg;
+
+ for (Reg = 0x54; Reg <= 0x57; Reg++) //clear the map-reg
+ {
+ Data = 0;
+ pci_write_config8(MEMCTRL, Reg, Data);
+ }
+
+ Shift = 1;
+ for (PhyRankNO = 0; PhyRankNO < MAX_RANKS; PhyRankNO++) {
+ if ((DramAttr->RankPresentMap & Shift) != 0) {
+ or = PhyRankNO; // get virtual Rank ,same with PhyRank
+ or |= 0x08;
+
+ if ((PhyRankNO & 0x01) == 0x01) // get mask for register
+ and = 0xf0;
+ else {
+ and = 0x0f;
+ or <<= 4;
+ }
+ DimmNO = (PhyRankNO >> 1);
+ Data = pci_read_config8(MEMCTRL, 0x54 + DimmNO);
+ Data &= and;
+ Data |= or;
+ pci_write_config8(MEMCTRL, 0x54 + DimmNO, Data);
+ }
+ Shift <<= 1;
+ }
+}
diff --git a/src/northbridge/via/vx800/ddr2init/vx800/TimingSetting.c b/src/northbridge/via/vx800/ddr2init/vx800/TimingSetting.c
new file mode 100644
index 0000000000..5e1847800a
--- /dev/null
+++ b/src/northbridge/via/vx800/ddr2init/vx800/TimingSetting.c
@@ -0,0 +1,492 @@
+/*
+ * 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
+ */
+
+ /*
+ Set Dram Timing functions
+ */
+
+void SetCL(DRAM_SYS_ATTR * DramAttr);
+
+void SetTrp(DRAM_SYS_ATTR * DramAttr);
+
+void SetTrcd(DRAM_SYS_ATTR * DramAttr);
+
+void SetTras(DRAM_SYS_ATTR * DramAttr);
+
+void SetTrfc(DRAM_SYS_ATTR * DramAttr);
+
+void SetTrrd(DRAM_SYS_ATTR * DramAttr);
+
+void SetTwr(DRAM_SYS_ATTR * DramAttr);
+
+void SetTwtr(DRAM_SYS_ATTR * DramAttr);
+
+void SetTrtp(DRAM_SYS_ATTR * DramAttr);
+
+/* Set DRAM Timing*/
+void DRAMTimingSetting(DRAM_SYS_ATTR * DramAttr)
+{
+ PRINT_DEBUG_MEM("Set CAS latency value!");
+ SetCL(DramAttr);
+
+ PRINT_DEBUG_MEM("Set tRP value!");
+ SetTrp(DramAttr);
+
+ PRINT_DEBUG_MEM("Set tRCD value!");
+ SetTrcd(DramAttr);
+
+ PRINT_DEBUG_MEM("Set tRAS value!");
+ SetTras(DramAttr);
+
+ PRINT_DEBUG_MEM("Set tRFC value!");
+ SetTrfc(DramAttr);
+
+ PRINT_DEBUG_MEM("Set tRRD value!");
+ SetTrrd(DramAttr);
+
+ PRINT_DEBUG_MEM("Set tWR value!");
+ SetTwr(DramAttr);
+
+ PRINT_DEBUG_MEM("Set tWTR value!");
+ SetTwtr(DramAttr);
+
+ PRINT_DEBUG_MEM("Set tRTP value!");
+ SetTrtp(DramAttr);
+}
+
+
+/*
+Set DRAM Timing: CAS Latency for DDR1
+D0F3RX62 bit[0:2] for CAS Latency;
+*/
+void SetCL(DRAM_SYS_ATTR * DramAttr)
+{
+ u8 Data;
+ u8 CL;
+
+ /*DDR2 CL Value: 20, 30, 40, 50 -> 2, 3, 4, 5 */
+ CL = (u8) ((DramAttr->CL - 20) / 10); //000,001,010,011
+
+ PRINT_DEBUG_MEM("CAS = ");
+ PRINT_DEBUG_MEM_HEX8(CL);
+ PRINT_DEBUG_MEM("\n");
+ Data = pci_read_config8(MEMCTRL, 0x62);
+ Data = (u8) ((Data & 0xf8) | CL);
+ pci_write_config8(MEMCTRL, 0x62, Data);
+}
+
+
+/*
+ Minimum row precharge time, Trp for DDR1/DDR2
+ D0F3Rx64[3:2] for Trp 2T~5T
+*/
+#define MAX_TRP 6
+#define MIN_TRP 2
+
+void SetTrp(DRAM_SYS_ATTR * DramAttr)
+{
+ u8 Data;
+ u16 Max, Tmp;
+ u8 Socket;
+
+
+ /*get the max Trp value from SPD data
+ SPD Byte27, Bit7:2->1ns~63ns, Bit1:0->0ns, 0.25ns, 0.50ns, 0.75ns */
+ Max = 0;
+ for (Socket = 0; Socket < MAX_SOCKETS; Socket++) {
+ if (DramAttr->DimmInfo[Socket].bPresence) {
+ Tmp =
+ (u16) (DramAttr->DimmInfo[Socket].
+ SPDDataBuf[SPD_SDRAM_TRP]);
+ if (Tmp > Max)
+ Max = Tmp;
+ }
+ /*Calculate clock,this value should be 2T,3T,4T,5T */
+ }
+ Tmp =
+ (u16) ((Max * 100 + ((DramAttr->DramCyc) << 2) -
+ 1) / ((DramAttr->DramCyc) << 2));
+ PRINT_DEBUG_MEM("Trp = ");
+ PRINT_DEBUG_MEM_HEX16(Tmp);
+ PRINT_DEBUG_MEM("\r");
+
+ if (Tmp > MAX_TRP)
+ Tmp = MAX_TRP;
+ else if (Tmp < MIN_TRP)
+ Tmp = MIN_TRP;
+
+ Tmp -= 2; //00->2T, 01->3T, 10->4T, 11->5T
+ Tmp <<= 1; //bit1,2,3
+
+ Data = pci_read_config8(MEMCTRL, 0x64);
+ Data = (u8) ((Data & 0xf1) | (u8) Tmp);
+ pci_write_config8(MEMCTRL, 0x64, Data);
+
+ //enable DDR2 8-Bank Device Timing Constraint
+ Data = pci_read_config8(MEMCTRL, 0x62);
+ Data = (u8) ((Data & 0xf7) | 0x08);
+ pci_write_config8(MEMCTRL, 0x62, Data);
+}
+
+
+/*
+Minimum RAS to CAS dely,Trcd for DDR1/DDR2
+D0F3Rx64[7:6] for Trcd
+*/
+#define MAX_TRCD 6
+#define MIN_TRCD 2
+
+void SetTrcd(DRAM_SYS_ATTR * DramAttr)
+{
+ u8 Data;
+ u16 Max, Tmp;
+ u8 Socket;
+
+
+ /*get the max Trcd value from SPD data
+ SPD Byte29, Bit7:2->1ns~63ns, Bit1:0->0ns, 0.25ns, 0.50ns, 0.75ns */
+ Max = 0;
+ for (Socket = 0; Socket < MAX_SOCKETS; Socket++) {
+ if (DramAttr->DimmInfo[Socket].bPresence) {
+ Tmp =
+ (u16) (DramAttr->DimmInfo[Socket].
+ SPDDataBuf[SPD_SDRAM_TRCD]);
+ if (Tmp > Max)
+ Max = Tmp;
+ }
+ }
+ /*Calculate clock,this value should be 2T,3T,4T,5T */
+ Tmp =
+ (u16) ((Max * 100 + ((DramAttr->DramCyc) << 2) -
+ 1) / ((DramAttr->DramCyc) << 2));
+ PRINT_DEBUG_MEM("Trcd =");
+ PRINT_DEBUG_MEM_HEX16(Tmp);
+ PRINT_DEBUG_MEM("\r");
+
+ if (Tmp > MAX_TRCD)
+ Tmp = MAX_TRCD;
+ else if (Tmp < MIN_TRCD)
+ Tmp = MIN_TRCD;
+ Tmp -= 2; //00->2T, 01->3T, 10->4T, 11->5T
+ Tmp <<= 5; //bit5,6,7
+
+ Data = pci_read_config8(MEMCTRL, 0x64);
+ Data = (u8) ((Data & 0x1f) | (u8) Tmp);
+ pci_write_config8(MEMCTRL, 0x64, Data);
+
+}
+
+/*
+ minimum active to precharge time,Tras for DDR1/DDR2
+ D0F3Rx62[7:4] Tras
+*/
+#define MAX_TRAS 20 //20T
+#define MIN_TRAS 5 //5T
+void SetTras(DRAM_SYS_ATTR * DramAttr)
+{
+ u8 Data;
+ u16 Max, Tmp;
+ u8 Socket;
+
+
+ /*get the max Tras value from SPD data
+ SPD byte30: bit0:7 1ns~255ns */
+ Max = 0;
+ for (Socket = 0; Socket < MAX_SOCKETS; Socket++) {
+ if (DramAttr->DimmInfo[Socket].bPresence) {
+ Tmp =
+ (u16) (DramAttr->DimmInfo[Socket].
+ SPDDataBuf[SPD_SDRAM_TRAS]);
+ if (Tmp > Max)
+ Max = Tmp;
+ }
+ }
+
+ /*Calculate clock,value range 5T-20T */
+ Tmp =
+ (u16) ((Max * 100 + DramAttr->DramCyc -
+ 1) / (DramAttr->DramCyc));
+ PRINT_DEBUG_MEM("Tras =");
+ PRINT_DEBUG_MEM_HEX16(Tmp);
+ PRINT_DEBUG_MEM("\r");
+
+ if (Tmp > MAX_TRAS)
+ Tmp = MAX_TRAS;
+ else if (Tmp < MIN_TRAS)
+ Tmp = MIN_TRAS;
+ Tmp -= 5; //0->5T ... 1111->20T
+ Tmp <<= 4; //bit4:7
+
+ Data = pci_read_config8(MEMCTRL, 0x62);
+ Data = (u8) ((Data & 0x0f) | (u8) Tmp);
+ pci_write_config8(MEMCTRL, 0x62, Data);
+}
+
+/*
+Minimum refresh to activate/refresh command period Trfc for DDR1/DDR2
+D0F3Rx61[5:0] for Trfc
+*/
+
+#define MAX_TRFC 71 // Max supported,71T
+#define MIN_TRFC 8 // Min supported,8T
+
+void SetTrfc(DRAM_SYS_ATTR * DramAttr)
+{
+
+ u8 Data;
+ u32 Max, Tmp;
+ u8 Byte40;
+ u8 Socket;
+
+ /*get the max Trfc value from SPD data */
+ Max = 0;
+ for (Socket = 0; Socket < MAX_SOCKETS; Socket++) {
+ if (DramAttr->DimmInfo[Socket].bPresence) {
+ Tmp =
+ (u32) (DramAttr->DimmInfo[Socket].
+ SPDDataBuf[SPD_SDRAM_TRFC]) * 100;
+ /*only DDR2 need to add byte 40 bit[7:4] */
+ Byte40 =
+ (DramAttr->DimmInfo[Socket].
+ SPDDataBuf[SPD_SDRAM_TRFC2]);
+ /*if bit0 = 1, byte42(RFC)+256ns, SPD spec JEDEC standard No.21.c */
+ if (Byte40 & 0x01)
+ Tmp += (256 * 100);
+ /*bit1,2,3 000->0ns+byte42; 001->0.25ns+byte42; 010->0.33ns+byte42; 011->0.5ns+byte42;100-> 0.75ns+byte42 */
+ switch ((Byte40 >> 1) & 0x07) { /*bit1,2,3 */
+ case 1:
+ Tmp += 25;
+ break;
+ case 2:
+ Tmp += 33;
+ break;
+ case 3:
+ Tmp += 50;
+ break;
+ case 4:
+ Tmp += 66;
+ break;
+ case 5:
+ Tmp += 75;
+ break;
+ case 6: //what is FRU???
+ default:
+ break;
+ }
+ if (Tmp > Max)
+ Max = Tmp;
+ }
+ }
+
+ /*Calculate clock,value range 8T-71T */
+ Tmp = (u16) ((Max + DramAttr->DramCyc - 1) / (DramAttr->DramCyc));
+ PRINT_DEBUG_MEM("Trfc = ");
+ PRINT_DEBUG_MEM_HEX16(Tmp);
+ PRINT_DEBUG_MEM("\r");
+ if (Tmp > MAX_TRFC)
+ Tmp = MAX_TRFC;
+ else if (Tmp < MIN_TRFC) {
+ // return;
+ Tmp = 0x40;
+ }
+ /*D0F3Rx61 bit[0:5] 0->8T ... 63->71T */
+ Tmp -= 8;
+
+ Data = pci_read_config8(MEMCTRL, 0x61);
+ Data = (u8) ((Data & 0xc0) | ((u8) Tmp & 0x3f));
+ pci_write_config8(MEMCTRL, 0x61, Data);
+}
+
+
+/*
+Minimum row active to row active delay: Trrd for DDR1/DDR2
+D0F3Rx61[7:6]:Trrd 00->2T, 01->3T, 10->4T, 11->5T
+*/
+#define MAX_TRRD 5
+#define MIN_TRRD 2
+
+void SetTrrd(DRAM_SYS_ATTR * DramAttr)
+{
+ u8 Data;
+ u16 Max, Tmp;
+ u8 Socket;
+
+
+ /*get the max Trrd value from SPD data
+ SPD Byte28, Bit7:2->1ns~63ns, Bit1:0->0ns, 0.25ns, 0.50ns, 0.75ns */
+ Max = 0;
+ for (Socket = 0; Socket < MAX_SOCKETS; Socket++) {
+ if (DramAttr->DimmInfo[Socket].bPresence) {
+ Tmp =
+ (u16) (DramAttr->DimmInfo[Socket].
+ SPDDataBuf[SPD_SDRAM_TRRD]);
+ if (Tmp > Max)
+ Max = Tmp;
+ }
+ }
+
+ /*Calculate clock,this value should be 2T,3T,4T,5T */
+ Tmp =
+ (u16) ((Max * 100 + ((DramAttr->DramCyc) << 2) -
+ 1) / ((DramAttr->DramCyc) << 2));
+ PRINT_DEBUG_MEM("Trrd =");
+ PRINT_DEBUG_MEM_HEX16(Tmp);
+ PRINT_DEBUG_MEM("\r");
+
+ if (Tmp > MAX_TRRD)
+ Tmp = MAX_TRRD;
+ else if (Tmp < MIN_TRRD)
+ Tmp = MIN_TRRD;
+ Tmp -= 2; //00->2T, 01->3T, 10->4T, 11->5T
+ Tmp <<= 6;
+
+ Data = pci_read_config8(MEMCTRL, 0x61);
+ Data = (u8) ((Data & 0x3f) | (u8) Tmp);
+ pci_write_config8(MEMCTRL, 0x61, Data);
+}
+
+
+/*
+Write recovery time: Twr for DDR1/DDR2
+Device 0 Function 3:REG63[7:5]:Twr 00->2T 01->3T 10->4T 11->5T
+*/
+#define MAX_TWR 6
+#define MIN_TWR 2
+
+void SetTwr(DRAM_SYS_ATTR * DramAttr)
+{
+ u8 Data;
+ u16 Max, Tmp;
+ u8 Socket;
+
+ /*get the max Trtp value from SPD data
+ SPD Byte36, Bit7:2->1ns~63ns, Bit1:0->0ns, 0.25ns, 0.50ns, 0.75ns */
+ Max = 0;
+ for (Socket = 0; Socket < MAX_SOCKETS; Socket++) {
+ if (DramAttr->DimmInfo[Socket].bPresence) {
+ Tmp =
+ (u16) (DramAttr->DimmInfo[Socket].
+ SPDDataBuf[SPD_SDRAM_TWR]);
+ if (Tmp > Max)
+ Max = Tmp;
+ }
+ }
+ /*Calculate clock */
+ Tmp = (u16) ((Max * 100 + ((DramAttr->DramCyc) << 2) - 1) / ((DramAttr->DramCyc) << 2)); //this value should be 2T,3T,4T,5T
+ PRINT_DEBUG_MEM("Twr = ");
+ PRINT_DEBUG_MEM_HEX16(Tmp);
+ PRINT_DEBUG_MEM("\r");
+
+ if (Tmp > MAX_TWR)
+ Tmp = MAX_TWR;
+ else if (Tmp < MIN_TWR)
+ Tmp = MIN_TWR;
+ Tmp -= 2; //00->2T, 01->3T, 10->4T, 11->5T
+ Tmp <<= 5;
+
+ Data = pci_read_config8(MEMCTRL, 0x63);
+ Data = (u8) ((Data & 0x1f) | (u8) Tmp);
+ pci_write_config8(MEMCTRL, 0x63, Data);
+}
+
+
+/*
+Internal write to read command delay: Twtr for DDR1/DDR2
+Device 0 Function 3:REG63[1,0]:Twtr DDR: 1T or 2T; DDR2 2T or 3T
+*/
+#define MAX_TWTR 5 //5T
+#define MIN_TWTR 2 //2T
+
+void SetTwtr(DRAM_SYS_ATTR * DramAttr)
+{
+ u8 Data;
+ u16 Max, Tmp;
+ u8 Socket;
+
+ /*get the max Trtp value from SPD data
+ SPD Byte37, Bit7:2->1ns~63ns, Bit1:0->0ns, 0.25ns, 0.50ns, 0.75ns */
+ Max = 0;
+ for (Socket = 0; Socket < MAX_SOCKETS; Socket++) {
+ if (DramAttr->DimmInfo[Socket].bPresence) {
+ Tmp =
+ (u16) (DramAttr->DimmInfo[Socket].
+ SPDDataBuf[SPD_SDRAM_TWTR]);
+ if (Tmp > Max)
+ Max = Tmp;
+ }
+ }
+ /*Calculate clock */
+ Tmp = (u16) ((Max * 100 + ((DramAttr->DramCyc) << 2) - 1) / ((DramAttr->DramCyc) << 2)); //this value should be 2T or 3T
+
+ PRINT_DEBUG_MEM("Twtr =");
+ PRINT_DEBUG_MEM_HEX16(Tmp);
+ PRINT_DEBUG_MEM("\r");
+
+ if (Tmp > MAX_TWR)
+ Tmp = MAX_TWTR;
+ else if (Tmp < MIN_TWR)
+ Tmp = MIN_TWTR;
+ Tmp -= 2; //00->2T, 01->3T, 10->4T, 11->5T
+ Data = pci_read_config8(MEMCTRL, 0x63);
+ Data = (u8) ((Data & 0xFC) | Tmp);
+ pci_write_config8(MEMCTRL, 0x63, Data);
+}
+
+
+/*
+Internal read to precharge command delay, Trtp for DDR1/DDR2
+Device 0 Function 3:REG63[3]:Trtp 2T or 3T
+*/
+#define MAX_TRTP 3 //3T
+#define MIN_TRTP 2 //2T
+
+void SetTrtp(DRAM_SYS_ATTR * DramAttr)
+{
+ u8 Data;
+ u16 Max, Tmp;
+ u8 Socket;
+
+
+ /*get the max Trtp value from SPD data
+ SPD Byte38, Bit7:2->1ns~63ns, Bit1:0->0ns, 0.25ns, 0.50ns, 0.75ns */
+ Max = 0;
+ for (Socket = 0; Socket < MAX_SOCKETS; Socket++) {
+ if (DramAttr->DimmInfo[Socket].bPresence) {
+ Tmp =
+ (u16) (DramAttr->DimmInfo[Socket].
+ SPDDataBuf[SPD_SDRAM_TRTP]);
+ if (Tmp > Max)
+ Max = Tmp;
+ }
+ }
+ /*Calculate clock */
+ Tmp = (u16) ((Max * 100 + ((DramAttr->DramCyc) << 2) - 1) / ((DramAttr->DramCyc) << 2)); //this value should be 2T or 3T
+
+ PRINT_DEBUG_MEM("Trtp =");
+ PRINT_DEBUG_MEM_HEX16(Tmp);
+ PRINT_DEBUG_MEM("\r");
+
+ Data = pci_read_config8(MEMCTRL, 0x63);
+ if (Tmp > MIN_TRTP)
+ Data = (u8) (Data | 0x08); /*set bit3, set 3T */
+ else
+ Data = (u8) (Data & 0xf7); /*clear bit3, set 2T */
+
+ pci_write_config8(MEMCTRL, 0x63, Data);
+}
diff --git a/src/northbridge/via/vx800/ddr2init/vx800/UMARamSetting.c b/src/northbridge/via/vx800/ddr2init/vx800/UMARamSetting.c
new file mode 100644
index 0000000000..f8aaf74eef
--- /dev/null
+++ b/src/northbridge/via/vx800/ddr2init/vx800/UMARamSetting.c
@@ -0,0 +1,445 @@
+/*
+ * 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
+ */
+
+typedef struct __UMA_RAM_tag {
+ u16 DramSize;
+ u8 D0F3Val;
+ u8 D1F0Val;
+ u8 VgaPortVal;
+} UMARAM;
+#define UMARAM_512M 7
+#define UMARAM_256M 6
+#define UMARAM_128M 5
+#define UMARAM_64M 4
+#define UMARAM_32M 3
+#define UMARAM_16M 2
+#define UMARAM_8M 1
+#define UMARAM_0M 0
+
+
+#define FB_512M 0
+#define FB_256M 0x40
+#define FB_128M 0x60
+#define FB_64M 0x70
+#define FB_32M 0x78
+#define FB_16M 0x7c
+#define FB_8M 0x7E
+#define FB_4M 0x7F
+
+#define VGA_PORT_512M 0x00
+#define VGA_PORT_256M 0x80
+#define VGA_PORT_128M 0xC0
+#define VGA_PORT_64M 0xE0
+#define VGA_PORT_32M 0xF0
+#define VGA_PORT_16M 0xF8
+
+static const UMARAM UMARamArr[] = {
+ {0, UMARAM_0M, FB_4M, 0xFE},
+ {8, UMARAM_8M, FB_8M, 0xFC},
+ {16, UMARAM_16M, FB_16M, VGA_PORT_16M},
+ {32, UMARAM_32M, FB_32M, VGA_PORT_32M},
+ {64, UMARAM_64M, FB_64M, VGA_PORT_64M},
+ {128, UMARAM_128M, FB_128M, VGA_PORT_128M},
+ {256, UMARAM_256M, FB_256M, VGA_PORT_256M},
+ {512, UMARAM_512M, FB_512M, VGA_PORT_512M},
+ {0xffff, 0xff, 0xff, 0xFF}
+};
+
+void SetUMARam(void)
+{
+#if 1
+ u8 ramregs[] = { 0x43, 0x42, 0x41, 0x40 };
+ device_t vga_dev = PCI_DEV(0, 1, 0), d0f0_dev = PCI_DEV(0, 0, 0);
+ u8 ByteVal, temp;
+ UMARAM *pUMARamTable;
+ u16 UmaSize;
+ u8 SLD0F3Val, SLD1F0Val, VgaPortVal;
+ u32 RamSize, SLBase, Tmp;
+ u8 i;
+ PRINT_DEBUG_MEM("Entering vx800 SetUMARam.\n");
+ SLD0F3Val = 0;
+ SLD1F0Val = 0;
+ VgaPortVal = 0;
+
+
+ ByteVal = pci_read_config8(MEMCTRL, 0xa1);
+ ByteVal |= 0x80;
+ pci_write_config8(MEMCTRL, 0xa1, ByteVal);
+
+ //set VGA Timer
+ pci_write_config8(MEMCTRL, 0xa2, 0xee);
+
+ //set agp misc
+ //GFX Data Delay to Sync with Clock
+ pci_write_config8(MEMCTRL, 0xa4, 0x01);
+
+ //page register life timer
+ pci_write_config8(MEMCTRL, 0xa6, 0x76);
+
+ //GMINT and GFX relatate
+ //note Bit 3 VGA Enable
+ pci_write_config8(MEMCTRL, 0xa7, 0x8c);
+ // ByteVal = 0x4c;
+
+ //GMINT Misc.1
+ //pci_write_config8(MEMCTRL, 0xb0, 0x80);
+
+ //pci_write_config8(MEMCTRL, 0xb1, 0xaa);
+
+ //AGPCINT MISC
+ //pci_write_config8(MEMCTRL, 0xb2, 0x82);
+ //ByteVal = 0x8A;
+
+ //GMINT MISC.2
+ //disable read pass write
+ pci_write_config8(MEMCTRL, 0xb3, 0x9A);
+
+ //EPLL Register
+ //pci_write_config8(MEMCTRL, 0xb4, 0x04);
+
+ //enable CHA and CHB merge mode
+ pci_write_config8(MEMCTRL, 0xde, 0x06);
+
+ //if can get the value from setup interface, so get the value
+ //else use the default value
+ UmaSize = CONFIG_VIDEO_MB;
+
+ for (pUMARamTable = UMARamArr; pUMARamTable->DramSize != 0xffff;
+ pUMARamTable++) {
+ if (UmaSize == pUMARamTable->DramSize) {
+ SLD0F3Val = pUMARamTable->D0F3Val;
+ SLD1F0Val = pUMARamTable->D1F0Val;
+ VgaPortVal = pUMARamTable->VgaPortVal;
+ }
+ }
+ //set SL size
+ //Fill in Fun3_RXA1[6:4] with the Frame Buffer size for the Integrated Graphic Device.
+ ByteVal = pci_read_config8(MEMCTRL, 0xa1);
+ ByteVal = (ByteVal & 0x8f) | (SLD0F3Val << 4);
+ pci_write_config8(MEMCTRL, 0xa1, ByteVal);
+
+
+// vga_dev = dev_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX855_VGA, 0);
+
+ //RxB2 may be for S.L. and RxB1 may be for L. L.
+ // It is different from Spec.
+ ByteVal = SLD1F0Val;
+ pci_write_config8(vga_dev, 0xb2, ByteVal);
+
+
+ //set M1 size
+ //ByteVal=pci_read_config8(MEMCTRL, 0xa3);
+ //ByteVal = 0x02;
+ //pci_write_config8(MEMCTRL, 0xa3, ByteVal);
+
+ PRINT_DEBUG_MEM("UMA setting - 3\n");
+
+
+
+
+ //Enable p2p IO/mem
+ ByteVal = 0x07;
+ pci_write_config8(vga_dev, 0x04, ByteVal);
+
+
+
+
+ //must set SL and MMIO base, or else when enable GFX memory space, system will hang
+ //set S.L base
+ Tmp = pci_read_config32(vga_dev, 0x10);
+ Tmp = 0xfffffff8;
+ pci_write_config32(vga_dev, 0x10, Tmp);
+ Tmp = pci_read_config32(vga_dev, 0x10);
+ Tmp = VIACONFIG_VGA_PCI_10;
+ pci_write_config32(vga_dev, 0x10, Tmp);
+
+ //set MMIO base
+ Tmp = pci_read_config32(vga_dev, 0x14);
+ Tmp = 0xfffffffC;
+ pci_write_config32(vga_dev, 0x14, Tmp);
+ Tmp = pci_read_config32(vga_dev, 0x14);
+ Tmp = VIACONFIG_VGA_PCI_14;
+ pci_write_config32(vga_dev, 0x14, Tmp);
+
+
+//enable direct cpu frame buffer access
+ i = pci_rawread_config8(PCI_RAWDEV(0, 0, 3), 0xa1);
+ i = (i & 0xf0) | (VIACONFIG_VGA_PCI_10 >> 28);
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0, 3), 0xa1, i);
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0, 3), 0xa0, 0x01);
+
+
+ //enable GFx memory space access control for S.L and mmio
+ ByteVal = pci_read_config8(d0f0_dev, 0xD4);
+ ByteVal |= 0x03;
+ //ByteVal |= 0x01;
+ pci_write_config8(d0f0_dev, 0xD4, ByteVal);
+
+
+ //enable Base VGA 16 Bits Decode
+ ByteVal = pci_read_config8(d0f0_dev, 0xfe);
+ ByteVal |= 0x10;
+ pci_write_config8(d0f0_dev, 0xfe, ByteVal);
+
+
+ //disable CHB L.L
+ //set VGA memory selection
+ ByteVal = pci_read_config8(vga_dev, 0xb0);
+ ByteVal &= 0xF8;
+ //ByteVal |= 0x01;
+ ByteVal |= 0x03;
+ pci_write_config8(vga_dev, 0xb0, ByteVal);
+
+ //set LL size
+
+ //enable memory access to SL,MMIO,LL and IO to 3B0~3BB,3C0 ~3DF
+ //ByteVal = 0x03;
+ //pci_write_config8(d0f0_dev, 0xc0, ByteVal);
+
+ //Turn on Graphic chip IO port port access
+ ByteVal = inb(0x03C3);
+ ByteVal |= 0x01;
+ outb(ByteVal, 0x03C3);
+
+ //Turn off Graphic chip Register protection
+ outb(0x10, 0x03C4);
+
+ ByteVal = inb(0x03C5);
+ ByteVal |= 0x01;
+ outb(ByteVal, 0x03C5);
+
+ //set VGA memory Frequence
+ //direct IO port 0x3DX to vga io space 0x3C2[0]
+ ByteVal = inb(0x03CC);
+ ByteVal |= 0x03;
+ outb(ByteVal, 0x03C2);
+ // ByteVal=inb(0x03C2);
+ // ByteVal |= 0x01;
+ // outb(ByteVal,0x03C2);
+
+
+#if 1 //bios porting guide has no this two defination: 3d on 3d4/3d5 and 39 on 3c4/3c5
+ //set frequence 0x3D5.3d[7:4]
+ outb(0x3d, 0x03d4);
+
+ temp = pci_read_config8(MEMCTRL, 0x90);
+ temp = (u8) (temp & 0x07);
+ ByteVal = inb(0x03d5);
+ switch (temp) {
+ case 0: //DIMMFREQ_200:
+ ByteVal = (u8) ((ByteVal & 0x0F) | 0x30);
+ break;
+ case 1: //DIMMFREQ_266:
+ ByteVal = (u8) ((ByteVal & 0x0F) | 0x40);
+ break;
+ case 3: //DIMMFREQ_400:
+ ByteVal = (u8) ((ByteVal & 0x0F) | 0x60);
+ break;
+ case 4: //DIMMFREQ_533:
+ ByteVal = (u8) ((ByteVal & 0x0F) | 0x70);
+ break;
+ case 5: //DIMMFREQ_667:
+ ByteVal = (u8) ((ByteVal & 0x0F) | 0x80);
+ break;
+ case 6: //DIMMFREQ_800:
+ ByteVal = (u8) ((ByteVal & 0x0F) | 0x90);
+ break;
+ default:
+ ByteVal = (u8) ((ByteVal & 0x0F) | 0x70);
+ break;
+ }
+ outb(ByteVal, 0x03d5);
+
+ // Set frame buffer size
+ outb(0x39, 0x03c4);
+ outb(1 << SLD0F3Val, 0x03c5);
+
+#endif
+ // Set S.L. size in GFX's register
+ outb(0x68, 0x03c4);
+ outb(VgaPortVal, 0x03c5);
+
+ // ECLK Selection (00:166Mhz, 01:185Mhz, 10:250Mhz, 11:275Mhz)
+ // set 3C5.5A[0]=1, address maps to secondary resgiters
+ outb(0x5a, 0x03c4);
+ ByteVal = inb(0x03c5);
+ ByteVal |= 0x01;
+ outb(ByteVal, 0x03c5);
+
+ // Set 3D5.4C[7:6] (00:166Mhz, 01:185Mhz, 10:250Mhz, 11:275Mhz)
+ outb(0x4c, 0x03d4);
+ ByteVal = inb(0x03d5);
+ ByteVal = (ByteVal & 0x3F) | 0x80;
+ outb(ByteVal, 0x03d5);
+
+ // set 3C5.5A[0]=0, address maps to first resgiters
+ outb(0x5a, 0x03c4);
+ ByteVal = inb(0x03c5);
+ ByteVal &= 0xFE;
+ outb(ByteVal, 0x03c5);
+
+ // Set S.L. Address in System Memory
+ //calculate dram size
+ for (RamSize = 0, i = 0; i < ARRAY_SIZE(ramregs); i++) {
+ RamSize = pci_read_config8(MEMCTRL, ramregs[i]);
+ if (RamSize != 0)
+ break;
+ }
+ //calculate SL Base Address
+ SLBase = (RamSize << 26) - (UmaSize << 20);
+
+
+ outb(0x6D, 0x03c4);
+ //SL Base[28:21]
+ outb((u8) ((SLBase >> 21) & 0xFF), 0x03c5);
+
+ outb(0x6e, 0x03c4);
+ //SL Base[36:29]
+ outb((u8) ((SLBase >> 29) & 0xFF), 0x03c5);
+
+ outb(0x6f, 0x03c4);
+ outb(0x00, 0x03c5);
+
+ // Set SVID high byte
+ outb(0x36, 0x03c4);
+ outb(0x11, 0x03c5);
+
+ // Set SVID Low byte
+ outb(0x35, 0x03c4);
+ outb(0x06, 0x03c5);
+
+ // Set SID high byte
+ outb(0x38, 0x03c4);
+ outb(0x51, 0x03c5);
+
+ // Set SID Low byte
+ outb(0x37, 0x03c4);
+ outb(0x22, 0x03c5);
+
+ //start : For enable snapshot mode control
+ // program 3C5 for SNAPSHOT Mode control, set RxF3h=1Ah
+ outb(0xf3, 0x03c4);
+ ByteVal = inb(0x03c5);
+ ByteVal = (ByteVal & 0xE5) | 0x1A;
+ outb(ByteVal, 0x03c5);
+
+
+ outb(0xf3, 0x03d4);
+ ByteVal = inb(0x03d5);
+ ByteVal = (ByteVal & 0xE5) | 0x1A;
+ outb(ByteVal, 0x03d5);
+
+ u8 table3c43c5[0x70] = {
+ 0x03, 0x01, 0x0F, 0x00, 0x06, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x78, 0x00, 0x00, 0x00, 0xBE, 0x20, 0x7F,
+ 0x60, 0x7F, 0x08, 0x31, 0xCC, 0x00, 0x01, 0x00,
+ 0x00, 0x18, 0x10, 0x00, 0x00, 0x00, 0x3D, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x04, 0xF3, 0xFF, 0xFC,
+ 0xF8, 0x0C, 0x00, 0x00, 0x40, 0x06, 0x11, 0x22,
+ 0x51, 0x10, 0x00, 0x01, 0x19, 0x0C, 0x00, 0xFF,
+ 0x38, 0x40, 0x30, 0xFF, 0x70, 0x8C, 0x85, 0x9D,
+ 0x80, 0x05, 0x54, 0x90, 0x03, 0x30, 0x00, 0x5F,
+ 0x1F, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00,
+ 0x06, 0xDF, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x20, 0x00, 0x20, 0x20,
+ 0xE0, 0x20, 0xD0, 0x3F, 0x00, 0xE0, 0x00, 0x00
+ };
+ u8 table3d43d5[0x88] = {
+ 0x7F, 0x63, 0x63, 0x83, 0x69, 0x19, 0x72, 0xE0,
+ 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x58, 0x9C, 0x57, 0x90, 0x00, 0x57, 0x73, 0xE3,
+ 0x57, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x0C, 0x00, 0x11, 0x06, 0x00, 0x20, 0x01, 0x34,
+ 0xEE, 0x74, 0x01, 0x01, 0x08, 0x84, 0x00, 0x00,
+ 0x00, 0xF3, 0x40, 0x90, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x12, 0x00, 0x02, 0x00, 0x00, 0x10, 0x00,
+ 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D,
+ 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x9D, 0x9D, 0x10,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x9D, 0x9D, 0x9D,
+ 0x9D, 0x9D, 0x9D, 0x9D, 0x00, 0x9D, 0x1D, 0x00,
+ 0x00, 0x00, 0x1D, 0x1D, 0x1D, 0x1D, 0x1D, 0x1D,
+ 0x1D, 0x1D, 0x1D, 0x1D, 0x1D, 0x1D, 0x1D, 0x1D,
+ };
+
+
+ u8 table3c0space[0xc0] = {
+ 0x11, 0x00, 0x10, 0x01, 0x26, 0x3D, 0xFF, 0x00,
+ 0x10, 0x3F, 0x00, 0x00, 0x2F, 0x00, 0x22, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x50, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ };
+#if 0
+//for(i=0;i<0xc0;i++)
+ for (i = 0; i < 0x40; i++) //
+ {
+ outb(table3c0space[i], 0x03c0 + i);
+ }
+
+
+ for (i = 0; i < 0x70; i++) {
+ outb(i, 0x03c4);
+ outb(table3c43c5[i], 0x03c5);
+ }
+ for (i = 0; i < 0x88; i++) {
+ outb(i, 0x03d4);
+ outb(table3d43d5[i], 0x03d5);
+ }
+ outb(0x92, 0x03d4);
+ outb(0x80, 0x03d5);
+
+ outb(0xa3, 0x03d4);
+ outb(0x00, 0x03d5);
+
+ outb(0xe8, 0x03d4);
+ outb(0x40, 0x03d5);
+#endif
+//3d4 3d freq
+//IO Port / Index: 3X5.3D
+//Scratch Pad Register 4
+
+// outb(0x39,0x03c4);//
+ //outb(1 << SLD0F3Val ,0x03c5);
+//
+#endif
+
+}
diff --git a/src/northbridge/via/vx800/examples/DrivingClkPhaseData.c b/src/northbridge/via/vx800/examples/DrivingClkPhaseData.c
new file mode 100644
index 0000000000..4028f02aa5
--- /dev/null
+++ b/src/northbridge/via/vx800/examples/DrivingClkPhaseData.c
@@ -0,0 +1,242 @@
+/*
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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
+ */
+
+ #include "northbridge/via/vx800/DrivingClkPhaseData.h"
+
+// DQS Driving
+//Reg0xE0, 0xE1
+// According to #Bank to set DRAM DQS Driving
+// #Bank 1 2 3 4 5 6 7 8
+static const u8 DDR2_DQSA_Driving_Table[4] = { 0xEE, 0xEE, 0xEE, 0xEE};
+static const u8 DDR2_DQSB_Driving_Table[2] = { 0xEE, 0xEE};
+
+// DQ Driving
+//Reg0xE2, 0xE3
+// For DDR2: According to bank to set DRAM DQ Driving
+static const u8 DDR2_DQA_Driving_Table[4] = { 0xAC, 0xAC, 0xAC, 0xAC };
+static const u8 DDR2_DQB_Driving_Table[2] = { 0xCA, 0xCA };
+
+
+// CS Driving
+//Reg0xE4, 0xE5
+// According to #Bank to set DRAM CS Driving
+// DDR1 #Bank 1 2 3 4 5 6 7 8
+static const u8 DDR2_CSA_Driving_Table_x8[4] = { 0x44, 0x44, 0x44, 0x44 };
+static const u8 DDR2_CSB_Driving_Table_x8[2] = { 0x44, 0x44};
+static const u8 DDR2_CSA_Driving_Table_x16[4]= { 0x44, 0x44, 0x44, 0x44};
+static const u8 DDR2_CSB_Driving_Table_x16[2]= { 0x44, 0x44};
+// MAA Driving
+//Reg0xE8, Reg0xE9
+static const u8 DDR2_MAA_Driving_Table[MA_Table][5] =
+ {
+ //Chip number, 400, 533, 667 800 ;(SRAS, SCAS, SWE)RxE8
+ { 6, 0x86, 0x86, 0x86, 0x86}, // total MAA chips = 00 ~ 06
+ { 18, 0x86, 0x86, 0x86, 0x86}, // total MAA chips = 06 ~ 18
+ {255, 0xDB, 0xDB, 0xDB, 0xDB} // total MAA chips = 18 ~
+ };
+
+static const u8 DDR2_MAB_Driving_Table[MA_Table][2] =
+ {
+ // Chip number, Value ;(SRAS, SCAS, SWE)RxE9
+ { 6, 0x86 }, // total MAB chips = 00 ~ 06
+ { 18, 0x86 }, // total MAB chips = 06 ~ 18
+ {255, 0xDB } // total MAB chips = 18 ~
+ };
+
+// DCLK Driving
+//Reg0xE6, 0xE7
+// For DDR2: According to #Freq to set DRAM DCLK Driving
+// freq 400M, 533M, 667M, 800M
+
+static const u8 DDR2_DCLKA_Driving_Table[4] = { 0xFF, 0xFF, 0xFF, 0xFF };
+static const u8 DDR2_DCLKB_Driving_Table[4] = { 0xFF, 0xFF, 0xFF, 0xFF };
+
+/*
+Duty cycle
+Duty cycle Control for DQ/DQS/DDRCKG in ChA & ChB
+D0F3RxEC/D0F3RxED/D0F3RxEE/D0F3RxEF
+According to DRAM frequency to control Duty Cycle
+*/
+static const u8 ChA_Duty_Control_DDR2[DUTY_CYCLE_REG_NUM][DUTY_CYCLE_FREQ_NUM] =
+ {
+ // (And NOT) DDR800 DDR667 DDR533 DDR400
+ //Reg Mask Value Value Value Value
+ {0xEC, 0x00, 0x30, 0x30, 0x30, 0x30 }, // 1Rank
+ {0xEE, 0x0F, 0x40, 0x40, 0x00, 0x00 },
+ {0xEF, 0xCF, 0x00, 0x30, 0x30, 0x30}
+ };
+
+static const u8 ChB_Duty_Control_DDR2[DUTY_CYCLE_REG_NUM][DUTY_CYCLE_FREQ_NUM] =
+ {
+ // (And NOT) DDR800 DDR667 DDR533 DDR400
+ //Reg Mask Value Value Value Value
+ {0xED, 0x00, 0x88, 0x88, 0x84, 0x88 }, // 1Rank
+ {0xEE, 0xF0, 0x00, 0x00, 0x00, 0x00 },
+ {0xEF, 0xFC, 0x00, 0x00, 0x00, 0x00 }
+ };
+
+
+/*
+DRAM Clock Phase Control for FeedBack Mode
+Modify NB Reg: Rx90[7]/Rx91/Rx92/Rx93/Rx94
+Processing:
+ 1.Program VIA_NB3DRAM_REG90[7]=0b for FeedBack mode
+ 2.Program clock phase value with ChA/B DCLK enable, VIA_NB3DRAM_REG91[7:3]=00b
+ 3.Check ChB rank #, if 0, VIA_NB3DRAM_REG91[7]=1b, to disable ChB DCLKO
+ ChA DCLKO can not be disable, so always program VIA_NB3DRAM_REG91[3]=0b
+ */
+static const u8 DDR2_ChA_Clk_Phase_Table_1R[3][Clk_Phase_Table_DDR2_Width] =
+ {
+ // (And NOT) DDR800 DDR667 DDR533 DDR400
+ //Reg Mask Value Value Value Value
+ {0x91, 0xF8, 0x02, 0x01, 0x00, 0x07 }, // 1Rank
+ {0x92, 0xF8, 0x04, 0x03, 0x03, 0x02 },
+ {0x93, 0xF8, 0x06, 0x05, 0x04, 0x03 }
+ };
+
+static const u8 DDR2_ChB_Clk_Phase_Table_1R[3][Clk_Phase_Table_DDR2_Width] =
+ {
+ // (And NOT) DDR800 DDR667 DDR533 DDR400
+ //Reg Mask Value Value Value Value
+ {0x91, 0x0F, 0x20, 0x10, 0x00, 0x70 }, // 1Rank
+ {0x92, 0x0F, 0x40, 0x30, 0x30, 0x20 },
+ {0x93, 0x0F, 0x60, 0x50, 0x40, 0x30 }
+ };
+
+/*static const u8 DDR2_ChA_Clk_Phase_Table_2R[3][Clk_Phase_Table_DDR2_Width] =
+ {
+ // (And NOT) DDR800 DDR667 DDR533 DDR400
+ //Reg Mask Value Value Value Value
+ {0x91, 0xF8, 0x04, 0x03, 0x04, 0x01 }, // 1Rank
+ {0x92, 0xF8, 0x03, 0x06, 0x05, 0x04 },
+ {0x93, 0xF8, 0x03, 0x07, 0x06, 0x05 }
+ };*/
+
+static const u8 DDR2_ChA_Clk_Phase_Table_2R[3][Clk_Phase_Table_DDR2_Width] =
+ {
+ // (And NOT) DDR800 DDR667 DDR533 DDR400
+ //Reg Mask Value Value Value Value
+ {0x91, 0xF8, 0x02, 0x01, 0x00, 0x07}, // 1Rank
+ {0x92, 0xF8, 0x04, 0x03, 0x03, 0x02 },
+ {0x93, 0xF8, 0x06, 0x05, 0x04, 0x03 }
+ };
+
+/*
+DRAM Write Data phase control
+Modify NB Reg: Rx74/Rx75/Rx76
+*/
+/*static const u8 DDR2_ChA_WrtData_Phase_Table[WrtData_REG_NUM ][WrtData_FREQ_NUM] =
+ {
+ // (And NOT) DDR800 DDR667 DDR533 DDR400
+ //Reg Mask Value Value Value Value
+ {0x74, 0xF8, 0x03, 0x04, 0x05, 0x02 }, // 1Rank
+ {0x75, 0xF8, 0x03, 0x04, 0x05, 0x02 },
+ {0x76, 0x00, 0x10, 0x80, 0x00, 0x07 }
+ };*/
+
+static const u8 DDR2_ChA_WrtData_Phase_Table[WrtData_REG_NUM ][WrtData_FREQ_NUM] =
+ {
+ // (And NOT) DDR800 DDR667 DDR533 DDR400
+ //Reg Mask Value Value Value Value
+ {0x74, 0xF8, 0x01, 0x00, 0x00, 0x07 }, // 1Rank
+ {0x75, 0xF8, 0x01, 0x00, 0x00, 0x07 },
+ {0x76, 0x10, 0x80, 0x87, 0x07, 0x06 },
+ {0x8C, 0xFC, 0x03, 0x03, 0x03, 0x03 }
+ };
+
+/*static const u8 DDR2_ChB_WrtData_Phase_Table[WrtData_REG_NUM ][WrtData_FREQ_NUM] =
+ {
+ // (And NOT) DDR800 DDR667 DDR533 DDR400
+ //Reg Mask Value Value Value Value
+ {0x74, 0x8F, 0x30, 0x40, 0x30, 0x20 }, // 1Rank
+ {0x75, 0x8F, 0x30, 0x40, 0x30, 0x20 },
+ {0x8A, 0x00, 0x10, 0x80, 0x07, 0x07 }
+ };
+*/
+/*
+DQ/DQS Output Delay Control
+Modify NB D0F3: RxF0/RxF1/RxF2/RxF3
+*/
+static const u8 DDR2_CHA_DQ_DQS_Delay_Table[4][DQ_DQS_Delay_Table_Width] =
+ {
+ // RxF0 RxF1 RxF2 RxF3
+ { 0x00, 0x00, 0x00, 0x00 },// DDR400
+ { 0x00, 0x00, 0x00, 0x00 },// DDR533
+ { 0x00, 0x00, 0x00, 0x00 },// DDR667
+ { 0x00, 0x00, 0x00, 0x00 }// DDR800
+ };
+static const u8 DDR2_CHB_DQ_DQS_Delay_Table[4][DQ_DQS_Delay_Table_Width] =
+ {
+ // RxF4 RxF5 RxF6 RxF7
+ { 0x00, 0x00, 0x00, 0x00 },// DDR400
+ { 0x00, 0x00, 0x00, 0x00 },// DDR533
+ { 0x00, 0x00, 0x00, 0x00 },// DDR667
+ { 0x00, 0x00, 0x00, 0x00 }// DDR800
+ };
+
+/*
+DQ/DQS input Capture Control
+modify NB D0F3_Reg:Rx78/Rx79/Rx7A/Rx7B
+*/
+
+/*static const u8 DDR2_ChA_DQS_Input_Capture_Tbl[DQS_INPUT_CAPTURE_REG_NUM ][DQS_INPUT_CAPTURE_FREQ_NUM] =
+ {
+ // (And NOT) DDR800 DDR667 DDR533 DDR400
+ //Reg Mask Value Value Value Value
+ {0x78, 0x00, 0x83, 0x8D, 0x87, 0x83 }, // 1Rank
+ {0x7A, 0xF0, 0x00, 0x00, 0x00, 0x00 },
+ {0x7B, 0x00, 0x10, 0x30, 0x20, 0x10 }
+ };*/
+
+
+static const u8 DDR2_ChA_DQS_Input_Capture_Tbl[DQS_INPUT_CAPTURE_REG_NUM ][DQS_INPUT_CAPTURE_FREQ_NUM] =
+ {
+ // (And NOT) DDR800 DDR667 DDR533 DDR400
+ //Reg Mask Value Value Value Value
+ {0x78, 0xC0, 0x0D, 0x07, 0x03, 0x01 }, // 1Rank
+ {0x7A, 0xF0, 0x00, 0x00, 0x00, 0x00 },
+ {0x7B, 0x00, 0x34, 0x34, 0x20, 0x10 }
+ };
+
+static const u8 DDR2_ChB_DQS_Input_Capture_Tbl[DQS_INPUT_CAPTURE_REG_NUM ][DQS_INPUT_CAPTURE_FREQ_NUM] =
+ {
+ // (And NOT) DDR800 DDR667 DDR533 DDR400
+ //Reg Mask Value Value Value Value
+ {0x79, 0x00, 0x89, 0x89, 0x87, 0x83 }, // 1Rank
+ {0x7A, 0x0F, 0x00, 0x00, 0x00, 0x00 },
+ {0x8B, 0x00, 0x34, 0x34, 0x20, 0x10 }
+ };
+
+static const u8 Fixed_DQSA_1_2_Rank_Table[4][2] =
+{
+// Rx70 Rx71
+ { 0x00, 0x05 }, // DDR800
+ { 0x00, 0x06 }, // DDR667
+ { 0x00, 0x04 }, // DDR533
+ { 0x00, 0x05 } // DDR400
+};
+static const u8 Fixed_DQSA_3_4_Rank_Table[4][2] =
+{
+// Rx70 Rx71
+ {0x00 , 0x04}, // DDR800
+ {0x00 , 0x04}, // DDR667
+ {0x00 , 0x03}, // DDR533
+ {0x00 , 0x04} // DDR400
+};
diff --git a/src/northbridge/via/vx800/examples/cache_as_ram_auto.c b/src/northbridge/via/vx800/examples/cache_as_ram_auto.c
new file mode 100644
index 0000000000..55468514e9
--- /dev/null
+++ b/src/northbridge/via/vx800/examples/cache_as_ram_auto.c
@@ -0,0 +1,660 @@
+/*
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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
+ */
+
+#define ASSEMBLY 1
+#define __ROMCC__
+#define RAMINIT_SYSINFO 1
+#define CACHE_AS_RAM_ADDRESS_DEBUG 0
+
+#include <stdint.h>
+#include <device/pci_def.h>
+#include <device/pci_ids.h>
+#include <arch/io.h>
+#include <device/pnp_def.h>
+#include <arch/romcc_io.h>
+#include <arch/hlt.h>
+#include "pc80/serial.c"
+#include "arch/i386/lib/console.c"
+#include "ram/ramtest.c"
+#include "northbridge/via/vx800/vx800.h"
+#include "cpu/x86/mtrr/earlymtrr.c"
+#include "cpu/x86/bist.h"
+#include "pc80/udelay_io.c"
+#include "lib/delay.c"
+#if CONFIG_USE_INIT == 0
+#include "lib/memcpy.c"
+#endif
+#include "cpu/x86/lapic/boot_cpu.c"
+
+#include "DrivingClkPhaseData.c"
+
+#include "northbridge/via/vx800/raminit.h"
+#include "northbridge/via/vx800/raminit.c"
+#include "cpu/x86/car/copy_and_run.c"
+
+int acpi_is_wakeup_early_via_vx800(void)
+{
+ device_t dev;
+ u16 tmp, result;
+
+ print_debug("In acpi_is_wakeup_early_via_vx800\r\n");
+ /* Power management controller */
+ dev = pci_locate_device(PCI_ID(PCI_VENDOR_ID_VIA,
+ PCI_DEVICE_ID_VIA_VX855_LPC), 0);
+
+ if (dev == PCI_DEV_INVALID)
+ die("Power management controller not found\r\n");
+
+ /* Set ACPI base address to I/O VX800_ACPI_IO_BASE. */
+ pci_write_config16(dev, 0x88, VX800_ACPI_IO_BASE | 0x1);
+
+ /* Enable ACPI accessm RTC signal gated with PSON. */
+ pci_write_config8(dev, 0x81, 0x84);
+
+ tmp = inw(VX800_ACPI_IO_BASE + 0x04);
+ result = ((tmp & (7 << 10)) >> 10) == 1 ? 3 : 0;
+ print_debug(" boot_mode=");
+ print_debug_hex16(result);
+ print_debug("\r\n");
+ return result;
+}
+
+static inline int spd_read_byte(unsigned device, unsigned address)
+{
+ return smbus_read_byte(device, address);
+}
+
+
+static void enable_mainboard_devices(void)
+{
+ device_t dev;
+ uint16_t values;
+
+ print_debug("In enable_mainboard_devices \r\n");
+
+ /*
+ Enable P2P Bridge Header for External PCI BUS.
+ */
+ dev = pci_locate_device(PCI_ID(0x1106, 0xa353), 0);
+ pci_write_config8(dev, 0x4f, 0x41);
+}
+
+static void enable_shadow_ram(void)
+{
+ uint8_t shadowreg;
+ pci_write_config8(PCI_DEV(0, 0, 3), 0x80, 0xff);
+ /* 0xf0000-0xfffff - ACPI tables */
+ shadowreg = pci_read_config8(PCI_DEV(0, 0, 3), 0x83);
+ shadowreg |= 0x30;
+ pci_write_config8(PCI_DEV(0, 0, 3), 0x83, shadowreg);
+ /* 0xe0000-0xeffff - elfload? */
+
+ pci_write_config8(PCI_DEV(0, 0, 3), 0x82, 0xff);
+
+}
+
+
+/*
+this table contains the value needed to be set before begin to init dram.
+Note: REV_Bx should be cared when porting a new board!!!!! */
+static const struct VIA_PCI_REG_INIT_TABLE mNbStage1InitTbl[] = {
+ //VT3409 no pcie
+ 0x00, 0xFF, NB_APIC_REG(0x61), 0xFF, 0x0E, // Set Exxxxxxx as pcie mmio config range
+ 0x00, 0xFF, NB_APIC_REG(0x60), 0xF4, 0x0B, // Support extended cfg address of pcie
+ //0x00, 0xFF, NB_APIC_REG(0x42), 0xF9, 0x02, // APIC Interrupt((BT_INTR)) Control
+ // Set ROMSIP value by software
+
+ /*0x00, 0xFF, NB_HOST_REG(0x70), 0x77, 0x33, // 2x Host Adr Strobe/Pad Pullup Driving = 3
+ 0x00, 0xFF, NB_HOST_REG(0x71), 0x77, 0x33, // 2x Host Adr Strobe/Pad Pulldown Driving = 3
+ 0x00, 0xFF, NB_HOST_REG(0x72), 0x77, 0x33, // 4x Host Dat Strobe/Pad Pullup Driving = 3
+ 0x00, 0xFF, NB_HOST_REG(0x73), 0x77, 0x33, // 4x Host Dat Strobe/Pad Pulldown Driving = 3
+ 0x00, 0xFF, NB_HOST_REG(0x74), 0xFF, 0x21, // Memory I/F timing ctrl
+ 0x00, 0xFF, NB_HOST_REG(0x74), 0xFF, 0xE1, // Memory I/F timing ctrl
+ 0x00, 0xFF, NB_HOST_REG(0x75), 0xFF, 0x18, // AGTL+ I/O Circuit
+ 0x00, 0xFF, NB_HOST_REG(0x76), 0xFB, 0x0C, // AGTL+ Compensation Status
+ 0x00, 0xFF, NB_HOST_REG(0x78), 0xFF, 0x33, // 2X AGTL+ Auto Compensation Offset
+ 0x00, 0xFF, NB_HOST_REG(0x79), 0xFF, 0x33, // 4X AGTL+ Auto Compensation Offset
+ 0x00, 0xFF, NB_HOST_REG(0x7A), 0x3F, 0x72, // AGTL Compensation Status
+ 0x00, 0xFF, NB_HOST_REG(0x7A), 0x3F, 0x77, // AGTL Compensation Status
+ 0x00, 0xFF, NB_HOST_REG(0x7B), 0xFF, 0x44, // Input Host Address / Host Strobe Delay Control for HA Group
+ 0x00, 0xFF, NB_HOST_REG(0x7B), 0xFF, 0x22, // Input Host Address / Host Strobe Delay Control for HA Group
+ 0x00, 0xFF, NB_HOST_REG(0x7C), 0xFF, 0x00, // Output Delay Control of PAD for HA Group
+ 0x00, 0xFF, NB_HOST_REG(0x7D), 0xFF, 0xAA, // Host Address / Address Clock Output Delay Control (Only for P4 Bus)
+ 0x00, 0xFF, NB_HOST_REG(0x7E), 0xFF, 0x10, // Host Address CKG Rising / Falling Time Control (Only for P4 Bus)
+ 0x00, 0xFF, NB_HOST_REG(0x7E), 0xFF, 0x40, // Host Address CKG Rising / Falling Time Control (Only for P4 Bus)
+ 0x00, 0xFF, NB_HOST_REG(0x7F), 0xFF, 0x10, // Host Address CKG Rising / Falling Time Control (Only for P4 Bus)
+ 0x00, 0xFF, NB_HOST_REG(0x7F), 0xFF, 0x40, // Host Address CKG Rising / Falling Time Control (Only for P4 Bus)
+ 0x00, 0xFF, NB_HOST_REG(0x80), 0x3F, 0x44, // Host Data Receiving Strobe Delay Ctrl 1
+ 0x00, 0xFF, NB_HOST_REG(0x81), 0xFF, 0x44, // Host Data Receiving Strobe Delay Ctrl 2
+ 0x00, 0xFF, NB_HOST_REG(0x82), 0xFF, 0x00, // Output Delay of PAD for HDSTB
+ 0x00, 0xFF, NB_HOST_REG(0x83), 0xFF, 0x00, // Output Delay of PAD for HD
+ 0x00, 0xFF, NB_HOST_REG(0x84), 0xFF, 0x44, // Host Data / Strobe CKG Control (Group 0)
+ 0x00, 0xFF, NB_HOST_REG(0x85), 0xFF, 0x44, // Host Data / Strobe CKG Control (Group 1)
+ 0x00, 0xFF, NB_HOST_REG(0x86), 0xFF, 0x44, // Host Data / Strobe CKG Control (Group 2)
+ 0x00, 0xFF, NB_HOST_REG(0x87), 0xFF, 0x44, // Host Data / Strobe CKG Control (Group 3) */
+
+
+ // CPU Host Bus Control
+ 0x00, 0xFF, NB_HOST_REG(0x50), 0x1F, 0x08, // Request phase ctrl: Dynamic Defer Snoop Stall Count = 8
+ //0x00, 0xFF, NB_HOST_REG(0x51), 0xFF, 0x7F, // CPU I/F Ctrl-1: Disable Fast DRDY and RAW
+ 0x00, 0xFF, NB_HOST_REG(0x51), 0xFF, 0x7C, // CPU I/F Ctrl-1: Disable Fast DRDY and RAW
+ 0x00, 0xFF, NB_HOST_REG(0x52), 0xCB, 0xCB, // CPU I/F Ctrl-2: Enable all for performance
+ //0x00, 0xFF, NB_HOST_REG(0x53), 0xFF, 0x88, // Arbitration: Host/Master Occupancy timer = 8*4 HCLK
+ 0x00, 0xFF, NB_HOST_REG(0x53), 0xFF, 0x44, // Arbitration: Host/Master Occupancy timer = 4*4 HCLK
+ 0x00, 0xFF, NB_HOST_REG(0x54), 0x1E, 0x1C, // Misc Ctrl: Enable 8QW burst Mem Access
+ //0x00, 0xFF, NB_HOST_REG(0x55), 0x06, 0x06, // Miscellaneous Control 2
+ 0x00, 0xFF, NB_HOST_REG(0x55), 0x06, 0x04, // Miscellaneous Control 2
+ 0x00, 0xFF, NB_HOST_REG(0x56), 0xF7, 0x63, // Write Policy 1
+ //0x00, 0xFF, NB_HOST_REG(0x59), 0x3D, 0x01, // CPU Miscellaneous Control 1, enable Lowest-Priority IPL
+ //0x00, 0xFF, NB_HOST_REG(0x5c), 0xFF, 0x00, // CPU Miscellaneous Control 2
+ 0x00, 0xFF, NB_HOST_REG(0x5D), 0xFF, 0xA2, // Write Policy
+ 0x00, 0xFF, NB_HOST_REG(0x5E), 0xFF, 0x88, // Bandwidth Timer
+ 0x00, 0xFF, NB_HOST_REG(0x5F), 0x46, 0x46, // CPU Misc Ctrl
+ // 0x00, 0xFF, NB_HOST_REG(0x90), 0xFF, 0x0B, // CPU Miscellaneous Control 3
+ //0x00, 0xFF, NB_HOST_REG(0x96), 0x0B, 0x0B, // CPU Miscellaneous Control 2
+ 0x00, 0xFF, NB_HOST_REG(0x96), 0x0B, 0x0A, // CPU Miscellaneous Control 2
+ 0x00, 0xFF, NB_HOST_REG(0x98), 0xC1, 0x41, // CPU Miscellaneous Control 3
+ 0x00, 0xFF, NB_HOST_REG(0x99), 0x0E, 0x06, // CPU Miscellaneous Control 4
+
+
+ // Set APIC and SMRAM
+ 0x00, 0xFF, NB_HOST_REG(0x97), 0xFF, 0x00, // APIC Related Control
+ 0x00, 0xFF, NB_DRAMC_REG(0x86), 0xD6, 0x29, // SMM and APIC Decoding: enable APIC, MSI and SMRAM A-Seg
+ 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // End of the table
+};
+
+#define USE_VCP 1 //0 means use DVP
+#define USE_COM1 1
+#define USE_COM2 0
+
+#define gCom1Base 0x3f8
+#define gCom2Base 0x2f8
+void EmbedComInit()
+{
+ u8 ByteVal;
+ u16 ComBase;
+
+ //enable NB multiple function control
+ ByteVal = pci_read_config8(PCI_DEV(0, 0, 0), 0x4f);
+ ByteVal = ByteVal | 0x01;
+ pci_write_config8(PCI_DEV(0, 0, 0), 0x4f, ByteVal);
+
+ //VGA Enable
+ ByteVal = pci_read_config8(PCI_DEV(0, 0, 3), 0xA1);
+ ByteVal = ByteVal | 0x80;
+ pci_write_config8(PCI_DEV(0, 0, 3), 0xA1, ByteVal);
+
+ ByteVal = pci_read_config8(PCI_DEV(0, 0, 3), 0xA7);
+ ByteVal = ByteVal | 0x08;
+ pci_write_config8(PCI_DEV(0, 0, 3), 0xA7, ByteVal);
+
+ //Enable p2p IO/mem
+ ByteVal = pci_read_config8(PCI_DEV(0, 1, 0), 0x4);
+ ByteVal = ByteVal | 0x07;
+ pci_write_config8(PCI_DEV(0, 1, 0), 0x4, ByteVal);
+
+ //Turn on Graphic chip IO port port access
+ ByteVal = inb(0x3C3);
+ ByteVal = ByteVal | 0x01;
+ outb(ByteVal, 0x3C3);
+
+ //Turn off Graphic chip Register protection
+ outb(0x10, 0x3C4);
+ ByteVal = inb(0x3C5);
+ ByteVal = ByteVal | 0x01;
+ outb(ByteVal, 0x3C5);
+
+ //south module pad share enable 0x3C5.78[7]
+ outb(0x78, 0x3C4);
+ ByteVal = inb(0x3C5);
+ ByteVal = ByteVal | 0x80;
+ outb(ByteVal, 0x3C5);
+
+ //enable UART Function multiplex with DVP or VCP pad D17F0Rx46[7,6]
+ ByteVal = pci_read_config8(PCI_DEV(0, 17, 0), 0x46);
+ //multiplex with VCP
+ if (USE_VCP == 1)
+ ByteVal = (ByteVal & 0x3F) | 0x40;
+ //multiplex with DVP
+ else
+ ByteVal = (ByteVal & 0x3F) | 0xC0;
+ pci_write_config8(PCI_DEV(0, 17, 0), 0x46, ByteVal);
+
+
+
+ //enable embeded com1 and com2 D17F0RxB0[5,4]
+ ByteVal = pci_read_config8(PCI_DEV(0, 17, 0), 0xB0);
+ ByteVal = ByteVal & 0xcf;
+ //multiplex with VCP
+ if (USE_COM1 == 1)
+ ByteVal = ByteVal | 0x10;
+ if (USE_COM2 == 1)
+ ByteVal = ByteVal | 0x20;
+ pci_write_config8(PCI_DEV(0, 17, 0), 0xB0, ByteVal);
+
+ if (USE_COM1 == 1)
+ ComBase = gCom1Base;
+ else
+ ComBase = gCom2Base;
+
+//noharddrive
+
+ //set embeded com1 IO base = 0x3E8
+ //D17F0RB4
+ //ByteVal = 0xFD;
+ if (USE_COM1 == 1) {
+ ByteVal = (u8) ((gCom1Base >> 3) | 0x80);
+ pci_write_config8(PCI_DEV(0, 17, 0), 0xB4, ByteVal);
+ ByteVal = pci_read_config8(PCI_DEV(0, 17, 0), 0xb2);
+ ByteVal = (ByteVal & 0xf0) | 0x04;
+ pci_write_config8(PCI_DEV(0, 17, 0), 0xB2, ByteVal);
+ }
+ //set embeded com2 IO base = 0x2E8
+ //D17F0RB5
+ //ByteVal = 0xDD;
+ if (USE_COM2 == 1) {
+ ByteVal = (u8) ((gCom2Base >> 3) | 0x80);
+ pci_write_config8(PCI_DEV(0, 17, 0), 0xB5, ByteVal);
+ ByteVal = pci_read_config8(PCI_DEV(0, 17, 0), 0xb2);
+ ByteVal = (ByteVal & 0x0f) | 0x30;
+ pci_write_config8(PCI_DEV(0, 17, 0), 0xB2, ByteVal);
+ }
+ //no port 80 biger then 0x10
+
+ //disable interrupt
+ ByteVal = inb(ComBase + 3);
+ outb(ByteVal & 0x7F, ComBase + 3);
+ outb(0x00, ComBase + 1);
+
+ //set baudrate
+ ByteVal = inb(ComBase + 3);
+ outb(ByteVal | 0x80, ComBase + 3);
+ outb(0x01, ComBase);
+ outb(0x00, ComBase + 1);
+
+ //set frame fromat
+ ByteVal = inb(ComBase + 3);
+ outb(ByteVal & 0x3F, ComBase + 3);
+ outb(0x03, ComBase + 3);
+ outb(0x00, ComBase + 2);
+ outb(0x00, ComBase + 4);
+
+ //SOutput("Embeded com output\n");
+ //while(1);
+}
+
+/* cache_as_ram.inc jump to here
+*/
+void amd64_main(unsigned long bist)
+{
+ unsigned cpu_reset = 0;
+ u16 boot_mode;
+ u8 rambits;
+
+ //device_t dev;
+ /* Enable multifunction for northbridge. */
+ pci_write_config8(PCI_DEV(0, 0, 0), 0x4f, 0x01);
+ EmbedComInit();
+ //enable_vx800_serial();
+ //uart_init();
+
+
+/* 1. D15F0
+
+a) RxBAh = 71h
+
+b) RxBBh = 05h
+
+c) RxBEh = 71h
+
+d) RxBFh = 05h
+
+2. D17F0
+
+a) RxA0h = 06h
+
+b) RxA1h = 11h
+
+c) RxA2h = 27h
+
+d) RxA3h = 32h
+
+e) Rx79h = 40h
+
+f) Rx72h = 27h
+
+g) Rx73h = 32h
+*/
+
+ u8 Data8;
+
+ pci_write_config16(PCI_DEV(0, 0xf, 0), 0xBA,
+ PCI_DEVICE_ID_VIA_VX855_IDE);
+ pci_write_config16(PCI_DEV(0, 0xf, 0), 0xBE,
+ PCI_DEVICE_ID_VIA_VX855_IDE);
+ pci_write_config16(PCI_DEV(0, 0x11, 0), 0xA0, PCI_VENDOR_ID_VIA);
+ pci_write_config16(PCI_DEV(0, 0x11, 0), 0xA2,
+ PCI_DEVICE_ID_VIA_VX855_LPC);
+ Data8 = pci_read_config8(PCI_DEV(0, 0x11, 0), 0x79);
+ Data8 &= ~0x40;
+ Data8 |= 0x40;
+ pci_write_config8(PCI_DEV(0, 0x11, 0), 0x79, Data8);
+ pci_write_config16(PCI_DEV(0, 0x11, 0), 0x72,
+ PCI_DEVICE_ID_VIA_VX855_LPC);
+
+ console_init(); //there are to function defination of console_init(), while the src/archi386/lib is the right one
+
+ /* decide if this is a s3 wakeup or a normal boot */
+ boot_mode = acpi_is_wakeup_early_via_vx800();
+ /*add this, to transfer "cpu restart" to "cold boot"
+ When this boot is not a S3 resume, and PCI registers had been written,
+ then this must be a cpu restart(result of os reboot cmd). so we need a real "cold boot". */
+ if ((boot_mode != 3)
+ && (pci_read_config8(PCI_DEV(0, 0, 3), 0x80) != 0)) {
+ outb(6, 0xcf9);
+ }
+
+ /*x86 cold boot I/O cmd */
+ enable_smbus();
+ //smbus_fixup(&ctrl);// this fix does help vx800!, but vx855 no need this
+
+ if (bist == 0) {
+ // CAR need mtrr untill mem is ok, so i disable this early_mtrr_init();
+ //print_debug("doing early_mtrr\r\n");
+ //early_mtrr_init();
+ }
+
+ /* Halt if there was a built-in self test failure. */
+ report_bist_failure(bist);
+
+ print_debug("Enabling mainboard devices\r\n");
+ enable_mainboard_devices();
+
+ u8 Data;
+ device_t device;
+ /* Get NB Chip revision from D0F4RxF6, revision will be used in via_pci_inittable */
+ device = PCI_DEV(0, 0, 4);
+ Data = pci_read_config8(device, 0xf6);
+ print_debug("NB chip revision =");
+ print_debug_hex8(Data);
+ print_debug("\r\n");
+ /* make NB ready before draminit */
+ via_pci_inittable(Data, mNbStage1InitTbl);
+
+ /*add this.
+ When resume from s3, draminit is skiped, so need to recovery any PCI register related to draminit.
+ and d0f3 didnt lost its Power during whole s3 time, so any register not belongs to d0f3 need to be recoveried . */
+#if 1
+ if (boot_mode == 3) {
+ u8 i;
+ u8 ramregs[] = { 0x43, 0x42, 0x41, 0x40 };
+ DRAM_SYS_ATTR DramAttr;
+
+ print_debug("This is a S3 wakeup\r\n");
+
+ memset(&DramAttr, 0, sizeof(DRAM_SYS_ATTR));
+ /*Step1 DRAM Detection; DDR1 or DDR2; Get SPD Data; Rank Presence;64 or 128bit; Unbuffered or registered; 1T or 2T */
+ DRAMDetect(&DramAttr);
+
+ /*begin to get ram size, 43,42 41 40 contains the end address of last rank in ddr2-slot */
+ device = PCI_DEV(0, 0, 3);
+ for (rambits = 0, i = 0; i < ARRAY_SIZE(ramregs); i++) {
+ rambits = pci_read_config8(device, ramregs[i]);
+ if (rambits != 0)
+ break;
+ }
+
+ DRAMDRDYSetting(&DramAttr);
+
+ Data = 0x80; // this value is same with DevInit.c
+ pci_write_config8(PCI_DEV(0, 0, 4), 0xa3, Data);
+ pci_write_config8(PCI_DEV(0, 17, 7), 0x60, rambits << 2);
+ Data = pci_read_config8(MEMCTRL, 0x88);
+ pci_write_config8(PCI_DEV(0, 17, 7), 0xE5, Data);
+
+ DRAMRegFinalValue(&DramAttr); // I just copy this function from draminit to here!
+ SetUMARam(); // I just copy this function from draminit to here!
+ print_debug("Resume from S3, RAM init was ignored\r\n");
+ } else {
+ ddr2_ram_setup();
+ ram_check(0, 640 * 1024);
+ }
+#endif
+ //ddr2_ram_setup();
+ /*this line is the same with cx700 port . */
+ enable_shadow_ram();
+
+ /*
+ For coreboot most time of S3 resume is the same as normal boot, so some memory area under 1M become dirty,
+ so before this happen, I need to backup the content of mem to top-mem.
+ I will reserve the 1M top-men in LBIO table in coreboot_table.c and recovery the content of 1M-mem in wakeup.c
+ */
+#if PAYLOAD_IS_SEABIOS==1 //
+ if (boot_mode == 3) {
+ /* some idea of Libo.Feng at amd.com in http://www.coreboot.org/pipermail/coreboot/2008-December/043111.html
+ I want move the 1M data, I have to set some MTRRs myself. */
+ /* seting mtrr before back memoy save s3 resume time about 0.14 seconds */
+ /*because CAR stack use cache, and here to use cache , must be careful,
+ 1 during these mtrr code, must no function call, (after this mtrr, I think it should be ok to use function)
+ 2 before stack switch, no use variable that have value set before this
+ 3 due to 2, take care of "cpu_reset", I directlly set it to ZERO.
+ */
+ u32 memtop = *(u32 *) WAKE_MEM_INFO;
+ u32 memtop1 = *(u32 *) WAKE_MEM_INFO - 0x100000;
+ u32 memtop2 = *(u32 *) WAKE_MEM_INFO - 0x200000;
+ u32 memtop3 =
+ *(u32 *) WAKE_MEM_INFO - 64 * 1024 - 0x100000;
+ u32 memtop4 =
+ *(u32 *) WAKE_MEM_INFO - 64 * 1024 - 0x100000 +
+ 0xe0000;
+ /* __asm__ volatile (
+ "movl $0x204, %%ecx\n\t"
+ "xorl %%edx, %%edx\n\t"
+ "movl %0,%%eax\n\t"
+ "orl $(0 | 6), %%eax\n\t"
+ "wrmsr\n\t"
+
+ "movl $0x205, %%ecx\n\t"
+ "xorl %%edx, %%edx\n\t"
+ "movl $0x100000,%%eax\n\t"
+ "decl %%eax\n\t"
+ "notl %%eax\n\t"
+ "orl $(0 | 0x800), %%eax\n\t"
+ "wrmsr\n\t"
+ ::"g"(memtop2)
+ );
+ __asm__ volatile (
+ "movl $0x206, %%ecx\n\t"
+ "xorl %%edx, %%edx\n\t"
+ "movl %0,%%eax\n\t"
+ "orl $(0 | 6), %%eax\n\t"
+ "wrmsr\n\t"
+
+ "movl $0x207, %%ecx\n\t"
+ "xorl %%edx, %%edx\n\t"
+ "movl $0x100000,%%eax\n\t"
+ "decl %%eax\n\t"
+ "notl %%eax\n\t"
+ "orl $(0 | 0x800), %%eax\n\t"
+ "wrmsr\n\t"
+ ::"g"(memtop1)
+ );
+ __asm__ volatile (
+ "movl $0x208, %ecx\n\t"
+ "xorl %edx, %edx\n\t"
+ "movl $0,%eax\n\t"
+ "orl $(0 | 6), %eax\n\t"
+ "wrmsr\n\t"
+
+ "movl $0x209, %ecx\n\t"
+ "xorl %edx, %edx\n\t"
+ "movl $0x100000,%eax\n\t"
+ "decl %eax\n\t"
+ "notl %eax\n\t"
+ "orl $(0 | 0x800), %eax\n\t"
+ "wrmsr\n\t"
+ );
+ */
+ // WAKE_MEM_INFO is inited in get_set_top_available_mem in tables.c
+ // these two memcpy not not be enabled if set the MTRR around this two lines.
+ /*__asm__ volatile (
+ "movl $0, %%esi\n\t"
+ "movl %0, %%edi\n\t"
+ "movl $0xa0000, %%ecx\n\t"
+ "shrl $2, %%ecx\n\t"
+ "rep movsd\n\t"
+ ::"g"(memtop3)
+ );
+ __asm__ volatile (
+ "movl $0xe0000, %%esi\n\t"
+ "movl %0, %%edi\n\t"
+ "movl $0x20000, %%ecx\n\t"
+ "shrl $2, %%ecx\n\t"
+ "rep movsd\n\t"
+ ::"g"(memtop4)
+ );*/
+ print_debug("copy memory to high memory to protect s3 wakeup vector code \r\n"); //this can have function call, because no variable used before this
+ memcpy((unsigned char *) ((*(u32 *) WAKE_MEM_INFO) -
+ 64 * 1024 - 0x100000),
+ (unsigned char *) 0, 0xa0000);
+ memcpy((unsigned char *) ((*(u32 *) WAKE_MEM_INFO) -
+ 64 * 1024 - 0x100000 + 0xe0000),
+ (unsigned char *) 0xe0000, 0x20000);
+
+ /* restore the MTRR previously modified. */
+/* __asm__ volatile (
+ "wbinvd\n\t"
+ "xorl %edx, %edx\n\t"
+ "xorl %eax, %eax\n\t"
+ "movl $0x204, %ecx\n\t"
+ "wrmsr\n\t"
+ "movl $0x205, %ecx\n\t"
+ "wrmsr\n\t"
+ "movl $0x206, %ecx\n\t"
+ "wrmsr\n\t"
+ "movl $0x207, %ecx\n\t"
+ "wrmsr\n\t"
+ "movl $0x208, %ecx\n\t"
+ "wrmsr\n\t"
+ "movl $0x209, %ecx\n\t"
+ "wrmsr\n\t"
+ );*/
+ }
+#endif
+/*
+the following code is copied from src\mainboard\tyan\s2735\cache_as_ram_auto.c
+Only the code around CLEAR_FIRST_1M_RAM is changed.
+I remove all the code around CLEAR_FIRST_1M_RAM and #include "cpu/x86/car/cache_as_ram_post.c"
+the CLEAR_FIRST_1M_RAM seems to make cpu/x86/car/cache_as_ram_post.c stop at somewhere,
+and cpu/x86/car/cache_as_ram_post.c do not cache my $XIP_ROM_BASE+SIZE area.
+
+So,I use: #include "cpu/via/car/cache_as_ram_post.c". my via-version post.c have some diff withx86-version
+*/
+#if 1
+ {
+ /* Check value of esp to verify if we have enough rom for stack in Cache as RAM */
+ unsigned v_esp;
+ __asm__ volatile ("movl %%esp, %0\n\t":"=a" (v_esp)
+ );
+#if CONFIG_USE_INIT
+ printk_debug("v_esp=%08x\r\n", v_esp);
+#else
+ print_debug("v_esp=");
+ print_debug_hex32(v_esp);
+ print_debug("\r\n");
+#endif
+ }
+
+#endif
+#if 1
+
+ cpu_reset_x:
+// it seems that cpu_reset is not used before this, so I just reset it, (this is because the s3 resume, setting in mtrr and copy data may destroy
+//stack
+ cpu_reset = 0;
+#if CONFIG_USE_INIT
+ printk_debug("cpu_reset = %08x\r\n", cpu_reset);
+#else
+ print_debug("cpu_reset = ");
+ print_debug_hex32(cpu_reset);
+ print_debug("\r\n");
+#endif
+
+ if (cpu_reset == 0) {
+ print_debug("Clearing initial memory region: ");
+ }
+ print_debug("No cache as ram now - ");
+
+ /* store cpu_reset to ebx */
+ __asm__ volatile ("movl %0, %%ebx\n\t"::"a" (cpu_reset)
+ );
+
+
+/* cancel these lines, CLEAR_FIRST_1M_RAM cause the cpu/x86/car/cache_as_ram_post.c stop at somewhere
+
+ if(cpu_reset==0) {
+#define CLEAR_FIRST_1M_RAM 1
+#include "cpu/via/car/cache_as_ram_post.c"
+ }
+ else {
+#undef CLEAR_FIRST_1M_RAM
+#include "cpu/via/car/cache_as_ram_post.c"
+ }
+*/
+#include "cpu/via/car/cache_as_ram_post.c"
+//#include "cpu/x86/car/cache_as_ram_post.c"
+ __asm__ volatile (
+ /* set new esp *//* before _RAMBASE */
+ "subl %0, %%ebp\n\t"
+ "subl %0, %%esp\n\t"::
+ "a" ((DCACHE_RAM_BASE + DCACHE_RAM_SIZE) -
+ _RAMBASE)
+ );
+
+ {
+ unsigned new_cpu_reset;
+
+ /* get back cpu_reset from ebx */
+ __asm__ volatile ("movl %%ebx, %0\n\t":"=a" (new_cpu_reset)
+ );
+
+ /* We can not go back any more, we lost old stack data in cache as ram */
+ if (new_cpu_reset == 0) {
+ print_debug("Use Ram as Stack now - done\r\n");
+ } else {
+ print_debug("Use Ram as Stack now - \r\n");
+ }
+#if CONFIG_USE_INIT
+ printk_debug("new_cpu_reset = %08x\r\n", new_cpu_reset);
+#else
+ print_debug("new_cpu_reset = ");
+ print_debug_hex32(new_cpu_reset);
+ print_debug("\r\n");
+#endif
+ /*copy and execute coreboot_ram */
+ copy_and_run(new_cpu_reset);
+ /* We will not return */
+ }
+#endif
+
+
+ print_debug("should not be here -\r\n");
+
+}
diff --git a/src/northbridge/via/vx800/examples/chipset_init.c b/src/northbridge/via/vx800/examples/chipset_init.c
new file mode 100644
index 0000000000..d4e7e40dec
--- /dev/null
+++ b/src/northbridge/via/vx800/examples/chipset_init.c
@@ -0,0 +1,1298 @@
+/*
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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
+ */
+
+#if HAVE_ACPI_RESUME == 1
+#include <arch/acpi.h>
+#endif
+#include <../northbridge/via/vx800/vx800.h>
+
+#include <arch/io.h>
+#include <arch/pci_rawops.h>
+
+static const struct VIA_PCI_REG_INIT_TABLE mSbStage1InitTbl[] = {
+ // Combine Stage1 registers
+ {0x00, 0xFF, SB_LPC_REG(0x41), 0x40, 0x40},
+
+ // Acpi init registers in sb stage1
+ {0x00, 0xFF, SB_LPC_REG(0x40), 0x04, 0x04}, // Enable 4D0/4D1 support
+ {0x00, 0xFF, SB_LPC_REG(0x4E), 0x00, 0x08}, // Enable RTC port 74/75
+ {0x00, 0xFF, SB_LPC_REG(0x51), 0x0D, 0x0D}, // and KBC
+ {0x00, 0xFF, SB_LPC_REG(0x52), 0x0F, 0x09}, // Enable Serial IRQ
+ {0x00, 0xFF, SB_LPC_REG(0x67), 0x00, 0x04}, // Set FERR voltage to 1.5v
+ {0x00, 0xFF, SB_LPC_REG(0x98), 0xFF, 0x00}, // Disable GP3 Timer
+
+ {0x00, 0xFF, SB_IDEC_REG(0xb9), 0x01, 0x01},
+
+ {0x00, 0xFF, SB_VLINK_REG(0xE6), 0xFF, 0x39}, // Enable SMM A-Seg, MSI and Io APIC
+ ///// SPI-BAR.
+ //// SPI_BASE_ADDRESS = 0xFED1 0000
+ 0x00, 0xFF, SB_LPC_REG(0xBC), 0xFF, 0x00,
+ 0x00, 0xFF, SB_LPC_REG(0xBD), 0xFF, 0xD1,
+ 0x00, 0xFF, SB_LPC_REG(0xBE), 0xFF, 0xFE,
+// 0x00, 0xFF, ((0x11<<16)|(0x00<<8)|0xBC), 0xFF, 0x00,//this , for the different macro
+// 0x00, 0xFF, ((0x11<<16)|(0x00<<8)|0xBD), 0xFF, 0xD1,
+// 0x00, 0xFF, ((0x11<<16)|(0x00<<8)|0xBE), 0xFF, 0xFE,
+ ///// End of 2008-04-17
+
+ {0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // End of Table
+};
+
+static const struct VIA_PCI_REG_INIT_TABLE mNbStage2InitTable[] = {
+ // D0F0: AGP Feature. For 3353, No AGP Feature
+
+ // D0F2~D0F3 is configured by MemoryInit Peim
+
+ // D0F4: NB PMU
+ 0x00, 0xFF, NB_PMU_REG(0x84), 0x00, 0xDB,
+ 0x00, 0xFF, NB_PMU_REG(0x85), 0x00, 0x05,
+ 0x00, 0xFF, NB_PMU_REG(0x89), 0x00, 0xF8,
+ 0x00, 0xFF, NB_PMU_REG(0x8B), 0x00, 0xBF,
+ 0x00, 0xFF, NB_PMU_REG(0x8D), 0x00, 0xFC,
+ 0x00, 0xFF, NB_PMU_REG(0x8E), 0x00, 0x19,
+ 0x00, 0xFF, NB_PMU_REG(0x8F), 0x03, 0x00,
+ 0x00, 0xFF, NB_PMU_REG(0x90), 0x00, 0xFF,
+ 0x00, 0xFF, NB_PMU_REG(0x91), 0x00, 0xFF,
+ 0x00, 0xFF, NB_PMU_REG(0x92), 0x00, 0xCC,
+ 0x00, 0xFF, NB_PMU_REG(0xA0), 0x00, 0x80,
+ 0x00, 0xFF, NB_PMU_REG(0xA1), 0x00, 0xE0,
+ 0x00, 0xFF, NB_PMU_REG(0xA2), 0x00, 0xD6,
+ 0x00, 0xFF, NB_PMU_REG(0xA3), 0x00, 0x80,
+ 0x00, 0xFF, NB_PMU_REG(0xA8), 0x00, 0x20,
+
+ // D0F5: NB APIC, PXPTRF and MSGC
+ //Note: the Rx6A, RCRBH Base Address, is not set, which is related to PCIE Root Complex.
+ //Note: the Rx60, Extended CFG Address. Support and Rx61, Extended CFG Address, are set by NB Peim that is in the PEI Phase.
+ //Note: the Rx42, APIC Interrupt((BT_INTR)) Control, is set by NB Peim that is in PEI phase.
+ 0x00, 0xFF, NB_PXPTRF_REG(0x50), 0x00, 0x00,
+ 0x00, 0xFF, NB_PXPTRF_REG(0x54), 0x00, 0x80,
+ 0x00, 0xFF, NB_PXPTRF_REG(0x55), 0x00, 0x04,
+ 0x00, 0xFF, NB_PXPTRF_REG(0x58), 0x00, 0x00,
+ 0x00, 0xFF, NB_PXPTRF_REG(0x59), 0x00, 0x02,
+ 0x00, 0xFF, NB_PXPTRF_REG(0x5E), 0x00, 0x00,
+ 0x00, 0xFF, NB_PXPTRF_REG(0x5F), 0x00, 0x06,
+ 0x00, 0xFF, NB_PXPTRF_REG(0x80), 0x00, 0x18, //Set RVC1DM, RTHBHIT, RUWRDYD, RUPRRDY1, RUWPOPHD to 1.
+ 0x00, 0xFF, NB_PXPTRF_REG(0x82), 0x00, 0x00, //Set RVC1RPSW, RVC1RQ1T to 1.
+ 0x00, 0xFF, NB_PXPTRF_REG(0x83), 0x00, 0x81,
+ 0x00, 0xFF, NB_PXPTRF_REG(0x84), 0x00, 0x28,
+ 0x00, 0xFF, NB_PXPTRF_REG(0x85), 0x00, 0xC0,
+ 0x00, 0xFF, NB_MSGC_REG(0xA3), 0x00, 0x01, // RWAKEEN
+// 0x00, 0xFF, NB_PXPTRF_REG(0x64), 0x40, 0x00, //RTDNP2B32EN
+ 0x00, 0xFF, NB_PXPTRF_REG(0xF3), 0xFC, 0x20,
+ 0x00, 0xFF, NB_PXPTRF_REG(0x85), 0x00, 0x00, //RP2P1ABORT
+
+
+// fine-tune
+// If no settings, C7 will hang or reboot in XP, but CN will not.
+ 0x00, 0xFF, NB_HOST_REG(0x51), 0x84, 0x00,
+ 0x00, 0xFF, NB_HOST_REG(0x52), 0x0F, 0x03,
+ 0x00, 0xFF, NB_HOST_REG(0x54), 0x04, 0x00,
+ 0x00, 0xFF, NB_HOST_REG(0x55), 0x04, 0x00,
+ 0x00, 0xFF, NB_HOST_REG(0x59), 0x09, 0x01,
+ 0x00, 0xFF, NB_HOST_REG(0x5C), 0x10, 0x10,
+ 0x00, 0xFF, NB_HOST_REG(0x5F), 0x0E, 0x08,
+ 0x00, 0xFF, NB_HOST_REG(0x92), 0xFF, 0x04, // ACPI Base addr
+ 0x00, 0xFF, NB_HOST_REG(0x97), 0x01, 0x01, // APIC MSI
+ 0x00, 0xFF, NB_HOST_REG(0x99), 0x02, 0x00, // APIC MSI
+ //GTL
+ 0x00, 0xFF, NB_HOST_REG(0x73), 0xFF, 0x66,
+ 0x00, 0xFF, NB_HOST_REG(0xB2), 0xFF, 0x33,
+ 0x00, 0xFF, NB_HOST_REG(0xB3), 0xFF, 0x33,
+ 0x00, 0xFF, NB_HOST_REG(0xBC), 0xFF, 0x33,
+ 0x00, 0xFF, NB_HOST_REG(0xBD), 0xFF, 0x33,
+ 0x00, 0xFF, NB_HOST_REG(0xC5), 0x30, 0x20,
+ 0x00, 0xFF, NB_HOST_REG(0xC8), 0x10, 0x00,
+
+
+ // End of Table
+ {0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // End of Table
+
+};
+
+static const struct VIA_PCI_REG_INIT_TABLE mBusControllerInitTable[] = {
+ // D17F0: LPC
+ 0x00, 0xFF, SB_LPC_REG(0x40), 0x44, 0x44, // Enable I/O Recovery Time, 4D0/4D1 Support
+ 0x00, 0xFF, SB_LPC_REG(0x42), 0xF8, 0xF0, // ENLBUF, GINTREN, FLUSHEN, RBRSTRD
+ 0x00, 0xFF, SB_LPC_REG(0x43), 0x0F, 0x0B, // RENDTX, ENWBTO, ENRBTO
+ // 0x00, 0xFF, SB_LPC_REG(0x46), 0x00, 0x10, // It is related to INTH#
+ //0x00, 0xFF, SB_LPC_REG(0x48), 0x00, 0x0C, //RMRPW, RIRPW // Reserved in 409 by Eric
+
+ // Internal RTC, Mouse, Keyboard // set in PEI by Eric
+ //0x00, 0xFF, SB_LPC_REG(0x51), 0x10, 0x0D, // Enable Internal RTC, Internal PS2 Mouse/Keyboard
+
+ // RTC
+ 0x00, 0xFF, SB_LPC_REG(0x58), 0x00, 0x01, //RTC Rx32 Map to Centrury Byte
+
+ // 0x00, 0xFF, SB_LPC_REG(0x40), 0x00, 0x02, // RDMEGAS
+ //0x00, 0xFF, SB_LPC_REG(0x4E), 0x00, 0x08, // Enable RTC port 74/75, ENEXRTC // set in PEI by Eric
+
+ // Serial IRQ // set in PEI by Eric
+ //0x00, 0xFF, SB_LPC_REG(0x52), 0x0F, 0x09, // Enable Serial IRQ, Start Frame Width is 6 PCI Clock.
+
+ // Enable 4D0h/4D1h Port
+ //0x00, 0xFF, SB_LPC_REG(0x40), 0x00, 0x04, // EISAXT // set in PEI by Eric
+
+ // Config ROM Interface
+ // Enable SPI/Set SPI Memory Base Address
+ // It is initialized in PEI Phase
+
+ // Subsystem ID/Vendor ID Back Door
+ 0x00, 0xFF, SB_LPC_REG(0x70), 0xFF, 0x06,
+ 0x00, 0xFF, SB_LPC_REG(0x71), 0xFF, 0x11,
+ 0x00, 0xFF, SB_LPC_REG(0x72), 0xFF, 0x09,
+ 0x00, 0xFF, SB_LPC_REG(0x73), 0xFF, 0x34,
+
+ 0x00, 0xFF, SB_LPC_REG(0x4C), 0xC0, 0x40,
+ 0x00, 0xFF, SB_LPC_REG(0x5B), 0x00, 0x51, // Orgin value 0x53, modify for 409 by Eric
+ 0x00, 0xFF, SB_LPC_REG(0x67), 0x03, 0x01,
+
+
+ 0x00, 0xFF, SB_LPC_REG(0x50), 0x7E, 0x00, // Setting PCI device enable
+ 0x00, 0xFF, SB_LPC_REG(0x51), 0xD0, 0x00, // Setting PCI device enable
+ 0x00, 0xFF, SB_VLINK_REG(0xD1), 0x04, 0x00, // Setting HDAC enable
+ {0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // End of Table
+};
+
+static const struct VIA_PCI_REG_INIT_TABLE mPCI1InitTable[] = {
+ //PCI1 Programming Sequence
+ //(1)Configure D17F7
+ 0x00, 0xFF, SB_VLINK_REG(0x04), 0x00, 0x03,
+ 0x00, 0xFF, SB_VLINK_REG(0x0C), 0x00, 0x08, // Reserved in 409 by Eric
+ 0x00, 0xFF, SB_VLINK_REG(0x4F), 0x40, 0x41, //RENPPB, RP2CFLSH
+ 0x00, 0xFF, SB_VLINK_REG(0x77), 0x00, 0x48, //ROP2CFLSH, RFFTMR[1:0]. ROP2CFLSH work with Rx4F[0](RP2CFLSH) assertion
+ // 0x00, 0xFF, SB_VLINK_REG(0x51), 0x00, 0x80, //RSUB_DEC_P2P, RSUBDECOD(Window xp). If Bit7 is set, PCI lock will occured.
+ //0x00, 0xFF, SB_VLINK_REG(0x51), 0x00, 0x81, //RSUB_DEC_P2P, RSUBDECOD(Window Vista)
+ //(2)Configure D19F0
+ 0x00, 0xFF, SB_P2PB_REG(0x04), 0x00, 0x07,
+
+ //(3)Performance Recommended Setting
+
+ //Save Power
+ 0x00, 0xFF, SB_VLINK_REG(0xE2), 0x1F, 0x01,
+ 0x00, 0xFF, SB_VLINK_REG(0xE3), 0xF1, 0x5E,
+ 0x00, 0xFF, SB_VLINK_REG(0x74), 0x40, 0x00,
+ //Enhence Host To PCI cycle performance and PCI-To-Host Cycle performance
+ 0x00, 0xFF, SB_VLINK_REG(0x70), 0x00, 0x82,
+ 0x00, 0xFF, SB_VLINK_REG(0x71), 0x30, 0xC0,
+ 0x00, 0xFF, SB_VLINK_REG(0x72), 0x00, 0xEE,
+
+ //Cycle Control
+ 0x00, 0xFF, SB_VLINK_REG(0x73), 0x00, 0x01,
+ 0x00, 0xFF, SB_VLINK_REG(0x74), 0x00, 0x0C,
+ //Arbitration control
+ 0x00, 0xFF, SB_VLINK_REG(0x75), 0x00, 0x0F,
+ 0x00, 0xFF, SB_VLINK_REG(0x76), 0x00, 0xD0,
+ {0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // End of Table
+};
+
+static const struct VIA_PCI_REG_INIT_TABLE mCCAInitTable[] = {
+
+ 0x00, 0xFF, SB_VLINK_REG(0xFC), 0x02, 0x08, //RVWREQ, ROABKDOOR
+
+ //CCA's Register Programming sequence
+ 0x00, 0xFF, SB_VLINK_REG(0x50), 0x00, 0x08, //Config Azalia's upstream cycle high priority and other low priority
+ 0x00, 0xFF, SB_VLINK_REG(0x51), 0x40, 0x80, //Disable bypass asynchronous circuit
+ 0x00, 0xFF, SB_VLINK_REG(0x52), 0x00, 0x11, // Set SM Internal Device and HDAC Occupy Timer
+ 0x00, 0xFF, SB_VLINK_REG(0x53), 0x00, 0x11, // Set SM Internal Device and HDAC Promote Timer
+ 0x00, 0xFF, SB_VLINK_REG(0x54), 0xFF, 0x02, //Use SB internal devices's original REQ
+ 0x00, 0xFF, SB_VLINK_REG(0x73), 0x10, 0x00, //RPINOWSC. Enable APIC Cycle Block P2C Write Cycle
+ 0x00, 0xFF, SB_VLINK_REG(0x74), 0x00, 0x3C, //RLCKXP2C, RFSBVK.
+ 0x00, 0xFF, SB_VLINK_REG(0xE1), 0x07, 0x00, //RBLKAPIC, RAZC3
+ 0x00, 0xFF, SB_VLINK_REG(0x7C), 0x04, 0x02, //RNMIFSB, RFSBVK
+ 0x00, 0xFF, SB_VLINK_REG(0xE0), 0xF0, 0x90, //RCCA_NEWCLK, RCCA_CLKON. Use New dynamic clock scheme
+ 0x00, 0xFF, SB_VLINK_REG(0xE7), 0xFF, 0x00, //Let CCA use dynamic clock.
+ //The CCA is also relate to D17F0
+ // 0x00, 0xFF, SB_LPC_REG(0x49), 0x1F, 0x00, //Disable CCA Test Mode
+ 0x00, 0xFF, SB_LPC_REG(0x74), 0xFF, 0x00, // Let DMA cycles from internal devices directly go to NB // Reserved in 409 by Eric
+ {0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // End of Table
+};
+
+static const struct VIA_PCI_REG_INIT_TABLE IDEC_INIT[] = {
+
+ // 0x00, 0xFF, SB_IDEC_REG(0x09), 0x00, 0x05, //set to native mode
+ 0x00, 0xFF, SB_IDEC_REG(0x04), 0x00, 0x07,
+ //0x00, 0xFF, SB_VLINK_REG(0x7C), 0x00, 0x7F,
+ {0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // End of Table
+
+};
+
+static const struct VIA_PCI_REG_INIT_TABLE mSbApicInitTable[] = {
+ 0x00, 0xFF, SB_LPC_REG(0x4D), 0x04, 0x00,
+ 0x00, 0xFF, SB_LPC_REG(0x5B), 0x0E, 0x00,
+ 0x00, 0xFF, SB_LPC_REG(0x6C), 0x08, 0x00,
+ 0x00, 0xFF, SB_LPC_REG(0x58), 0x00, 0x40,
+ 0x00, 0xFF, SB_VLINK_REG(0x74), 0x00, 0x04,
+ //0x00, 0xFF, SB_VLINK_REG(0x7C), 0x00, 0x7F,
+ {0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // End of Table
+
+};
+
+
+
+void AcpiInit(void)
+{
+ device_t_raw rawdevice = 0;
+ u8 sbchiprev;
+ rawdevice = PCI_RAWDEV(0, 0x11, 0);
+ // Set the PMIO base io address
+ pci_rawmodify_config16(rawdevice, 0x88, VX800_ACPI_IO_BASE,
+ 0xff80);
+ // Enable PMIO
+ pci_rawmodify_config16(rawdevice, 0x80, 0x8000, 0x8000);
+ // Enable Soft Resume
+ outw(inw(VX800_ACPI_IO_BASE + 0x04) | 0x8000,
+ VX800_ACPI_IO_BASE + 0x04);
+
+ // Get SB Revision
+ sbchiprev = pci_rawread_config8(rawdevice, 0xf6);
+ printk_debug("SB chip revision =%x\n", sbchiprev);
+
+ // Fill Register Table
+ via_pci_inittable(sbchiprev, mSbStage1InitTbl);
+
+ // Close all SMI/Io Traps
+ outb(0x00, VX800_ACPI_IO_BASE + 0x42);
+
+}
+
+
+void Stage2NbInit(void)
+{
+ device_t_raw rawdevice = 0;
+ u8 nbchiprev;
+ u32 subid = 0;
+ rawdevice = PCI_RAWDEV(0, 0, 4);
+ nbchiprev = pci_rawread_config8(rawdevice, 0xf6);
+ printk_debug("NB chip revision =%x\n", nbchiprev);
+
+ via_pci_inittable(nbchiprev, mNbStage2InitTable);
+
+ rawdevice = PCI_RAWDEV(0, 0, 0);
+
+ subid = PCI_DEVICE_ID_VIA_VX855_D0F0 << 16 + PCI_VENDOR_ID_VIA;
+ pci_rawwrite_config32(rawdevice, 0x2C, subid);
+
+ //vx855 NB no pcie bus
+ //vx855 NB no apic
+
+}
+
+void IDECSupportOption(u8 sbchiprev)
+{
+ pci_rawmodify_config8(PCI_RAWDEV(0, 0x11, 0), 0x50, 0, 0x08);
+
+ pci_rawmodify_config8(PCI_RAWDEV(0, 0xf, 0), 0x45, 0x00, 0x80);
+ pci_rawmodify_config8(PCI_RAWDEV(0, 0xf, 0), 0x0A, 0x01, 0xFF);
+ pci_rawmodify_config8(PCI_RAWDEV(0, 0xf, 0), 0x45, 0x80, 0x00);
+ pci_rawmodify_config8(PCI_RAWDEV(0, 0xf, 0), 0x40, 0x02, 0x00);
+
+ pci_rawmodify_config8(PCI_RAWDEV(0, 0xf, 0), 0x09, 0x00, 0x05); //COMPATIBLE MODE
+// pci_rawmodify_config8(PCI_RAWDEV(0, 0xf, 0), 0x09, 0x05, 0x05);//native MODE
+
+ via_pci_inittable(sbchiprev, IDEC_INIT);
+}
+
+void InitIDEC(u8 sbchiprev)
+{
+ IDECSupportOption(sbchiprev);
+}
+
+
+void InitUHCI(u8 Number, u8 bEnable)
+{
+ u8 Mask, Value;
+ u16 D16;
+ u8 BaseAddress;
+ u8 BitShift;
+ // USB Device 16
+ // Function : Number
+ // 0 : 0
+ // 1 : 1
+ // 2 : 2
+ // The BitShift is got from Datasheet.
+
+ switch (Number) {
+ case 0:
+ BaseAddress = 0;
+ BitShift = 4;
+ break;
+ case 1:
+ BaseAddress = 1;
+ BitShift = 5;
+ break;
+ case 2:
+ default:
+ BaseAddress = 2;
+ BitShift = 2;
+ break;
+ }
+
+ if (bEnable) {
+ Mask = 0x1 << BitShift;
+ Value = 0x0;
+ } else {
+ Mask = 0x0;
+ Value = 0x1 << BitShift;
+ }
+ pci_rawmodify_config8(PCI_RAWDEV(0, 0x11, 0), 0x50, Value, Mask);
+
+
+ if (bEnable) {
+ D16 = 0;
+ pci_rawwrite_config16(PCI_RAWDEV(0, 0x10, BaseAddress),
+ 0x20, D16);
+
+ // Config some Control Register
+ Mask = 0x00;
+ Value = 0x12;
+
+ pci_rawmodify_config8(PCI_RAWDEV(0, 0x10, BaseAddress),
+ 0x41, Value, Mask);
+ Mask = 0x00;
+ Value = 0xEB;
+ pci_rawmodify_config8(PCI_RAWDEV(0, 0x10, BaseAddress),
+ 0x4B, Value, Mask);
+ }
+ return;
+}
+
+static const struct VIA_PCI_REG_INIT_TABLE mEHCIInitTable[] = {
+ //EHCI
+ 0x00, 0xFF, SB_EHCI_REG(0x43), 0x00, 0xC0,
+ 0x00, 0xFF, SB_EHCI_REG(0x50), 0x00, 0x80,
+ 0x00, 0xFF, SB_EHCI_REG(0x48), 0x20, 0x9E,
+ 0x00, 0xFF, SB_EHCI_REG(0x49), 0x10, 0x68,
+ 0x00, 0xFF, SB_EHCI_REG(0x4B), 0x00, 0x69,
+ 0x00, 0xFF, SB_EHCI_REG(0x4D), 0x00, 0x94,
+ 0x00, 0xFF, SB_EHCI_REG(0x52), 0x08, 0x00,
+ 0x00, 0xFF, SB_EHCI_REG(0x5A), 0x00, 0x8A,
+ 0x00, 0xFF, SB_EHCI_REG(0x5B), 0x00, 0x89,
+ 0x00, 0xFF, SB_EHCI_REG(0x5C), 0x00, 0x03,
+ 0x00, 0xFF, SB_EHCI_REG(0x5D), 0x00, 0x9A,
+ 0x00, 0xFF, SB_EHCI_REG(0x5E), 0x00, 0x00,
+ 0x00, 0xFF, SB_EHCI_REG(0x6B), 0x00, 0x00,
+ 0x00, 0xFF, SB_EHCI_REG(0x6D), 0x00, 0x00,
+ 0x00, 0xFF, SB_EHCI_REG(0x6F), 0xF0, 0x00,
+ 0x00, 0xFF, SB_EHCI_REG(0x4E), 0x01, 0x01,
+ 0x00, 0xFF, SB_EHCI_REG(0x4F), 0x00, 0x11,
+ {0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // End of Table
+
+};
+
+void InitEHCI(u8 Number, u8 bEnable)
+{
+ u8 Mask, Value;
+ u8 EHCIRevision;
+
+ if (bEnable) {
+ Mask = 0x1 << 1;
+ Value = 0x0;
+ } else {
+ Mask = 0x0;
+ Value = 0x1 << 1;
+ }
+ pci_rawmodify_config8(PCI_RAWDEV(0, 0x11, 0), 0x50, Value, Mask);
+
+
+ if (bEnable) {
+ // Get Chipset Revision
+ EHCIRevision =
+ pci_rawread_config8(PCI_RAWDEV(0, 0x10, 4), 0xF6);
+ printk_debug("EHCI Revision =%x\n", EHCIRevision);
+ via_pci_inittable(EHCIRevision, mEHCIInitTable);
+ }
+}
+
+#define TRUE 1
+void InitUSBC(u8 sbchiprev)
+{
+ InitUHCI(0, TRUE);
+ InitUHCI(1, TRUE);
+ InitUHCI(2, TRUE);
+ InitEHCI(0, TRUE);
+}
+
+void WriteSbApicIndexedReg(u8 Idx, u32 Data)
+{
+ u32 Data32;
+ u32 ApicIdxAdr = VX800SB_APIC_BASE;
+ u32 ApicDataAdr = VX800SB_APIC_BASE + VX800SB_APIC_DATA_OFFSET;
+ *((u8 *) ApicIdxAdr) = Idx;
+ Data32 = (*((u32 *) ApicDataAdr)); //this read is needed when write APIC ID ,dont know why.
+ Data32 = Data;
+ *((u32 *) ApicDataAdr) = Data32;
+}
+
+void SbApicMmioRegInit(void)
+{
+ u32 Offset;
+ WriteSbApicIndexedReg(3, 1);
+ WriteSbApicIndexedReg(0, 4);
+ for (Offset = 0x10; Offset < VX800SB_APIC_ENTRY_NUMBER;
+ Offset += 2) {
+ WriteSbApicIndexedReg(Offset + 1, 0);
+ WriteSbApicIndexedReg(Offset, 0x10000);
+ }
+}
+
+void SbApicInit(u8 sbchiprev)
+{
+ via_pci_inittable(sbchiprev, mSbApicInitTable);
+ SbApicMmioRegInit();
+}
+
+void SbAcpiInit(void)
+{
+ u8 Mask, Value;
+ // Enable ACPI
+ Mask = 0x01;
+ Value = 0x01;
+ io_rawmodify_config8(VX800_ACPI_IO_BASE + 0x04, Value, Mask);
+}
+
+#define HPET_ENABLE_BIT 0x80
+#define R_SB_HPET_CONTROL 0x68
+#define HPET_BASE_ADDRESS 0xFED0 // 0xFED00000
+#define R_SB_HPET_ADDRESS 0x69
+
+void HpetInit(void)
+{
+ u8 HpetEnable = HPET_ENABLE_BIT;
+ u16 HpetBase = HPET_BASE_ADDRESS;
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0x11, 0), R_SB_HPET_CONTROL,
+ HpetEnable);
+ pci_rawwrite_config16(PCI_RAWDEV(0, 0x11, 0),
+ R_SB_HPET_ADDRESS + 1, HpetBase);
+}
+
+static const struct VIA_PCI_REG_INIT_TABLE mPMUInitTable[] = {
+ // Power Management
+ 0x00, 0xFF, SB_LPC_REG(0x80), 0x00, 0x20,
+ 0x00, 0xFF, SB_LPC_REG(0x8C), 0x02, 0x00,
+ 0x00, 0xFF, SB_LPC_REG(0x8D), 0x00, 0x18,
+
+ //Miscellaneous Configuration 1
+ 0x00, 0xFF, SB_LPC_REG(0x94), 0xF0, 0x28,
+ 0x00, 0xFF, SB_LPC_REG(0x95), 0x00, 0xC1,
+ 0x00, 0xFF, SB_LPC_REG(0x96), 0xFF, 0x10,
+ 0x00, 0xFF, SB_LPC_REG(0x97), 0x00, 0xB2,
+
+ //Voltage Change Function Enable
+ 0x00, 0xFF, SB_LPC_REG(0x9F), 0x00, 0x21,
+ //Internal PCIe and NM PLL Control
+ 0x00, 0xFF, SB_LPC_REG(0xE2), 0x00, 0xEA,
+
+ 0x00, 0xFF, SB_LPC_REG(0xE7), 0x00, 0x80,
+ {0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // End of Table
+};
+
+void InitPMU(u8 sbchiprev)
+{
+ u8 Mask, Value;
+ // Set PMU Registers
+ via_pci_inittable(sbchiprev, mPMUInitTable);
+
+
+ // Set SCI IRQ and its level trigger
+ Mask = 0x0F;
+ Value = 0x09;
+ pci_rawmodify_config8(PCI_RAWDEV(0, 0x11, 0), 0x82, Value, Mask);
+
+ Mask = 0x02;
+ Value = 0x02;
+ io_rawmodify_config8(0x4d1, Value, Mask);
+}
+
+#define R_SB_MULTI_FUNCTION_SELECT_1 0xE4
+#define R_SB_CX_STATE_BREAK_EVENT_ENABLE_1 0xE6
+#define PMIO_PROCESSOR_CONTROL 0x26
+#define R_SB_PCI_ARBITRATION_2 0x76
+#define R_SB_AUTO_SWITCH_P_STATE 0x8A
+
+void InitCPUCStatueSupport()
+{
+ u8 Mask, Value;
+
+ // Config Cx State
+ // Now it is C2 & C4 Up Down Mode
+ Mask = 0xFF;
+ Value = 0x30;
+ pci_rawmodify_config8(PCI_RAWDEV(0, 0x11, 0), R_SB_CX_STATE_BREAK_EVENT_ENABLE_1, Value, Mask); //SB_LPC_REG
+
+ Mask = 0xFF;
+ Value = 0x1F;
+ io_rawmodify_config8(VX800_ACPI_IO_BASE + PMIO_PROCESSOR_CONTROL,
+ Value, Mask);
+
+ Mask = 0x00;
+ Value = 0x80;
+ pci_rawmodify_config8(PCI_RAWDEV(0, 0x11, 7), R_SB_PCI_ARBITRATION_2, Value, Mask); //SB_VLINK_REG
+
+ Mask = 0xFF;
+ Value = 0x00;
+ pci_rawmodify_config8(PCI_RAWDEV(0, 0x11, 0), R_SB_MULTI_FUNCTION_SELECT_1, Value, Mask); //SB_VLINK_REG
+
+ Mask = 0xFF;
+ Value = 0x1F;
+ pci_rawmodify_config8(PCI_RAWDEV(0, 0x11, 0), R_SB_AUTO_SWITCH_P_STATE, Value, Mask); //SB_VLINK_REG
+}
+
+void InitSBPM(u8 sbchiprev)
+{
+ InitPMU(sbchiprev);
+ SbAcpiInit();
+ InitCPUCStatueSupport();
+}
+
+void Stage2SbInit(void)
+{
+ device_t_raw rawdevice = 0;
+ u8 sbchiprev;
+
+ rawdevice = PCI_RAWDEV(0, 11, 0);
+ sbchiprev = pci_rawread_config8(rawdevice, 0xf6);
+ printk_debug("SB chip revision =%x\n", sbchiprev);
+
+ //SBBasicInit
+ via_pci_inittable(sbchiprev, mBusControllerInitTable);
+ via_pci_inittable(sbchiprev, mPCI1InitTable);
+ via_pci_inittable(sbchiprev, mCCAInitTable);
+
+
+ InitIDEC(sbchiprev);
+
+ InitUSBC(sbchiprev);
+
+ InitSBPM(sbchiprev);
+
+ SbApicInit(sbchiprev);
+
+ HpetInit();
+
+ //pci_rawmodify_config8(PCI_RAWDEV(0, 0x11, 0), 0x50, 0x76, 0);//SB_VLINK_REG
+
+}
+
+
+void init_VIA_chipset(void)
+{
+ printk_debug("In: init_VIA_chipset\n");
+ //1.nbstage1 is done in raminit.
+ //2.sbstage1
+ AcpiInit();
+ //3.nbstage2
+ Stage2NbInit();
+
+ //4.sbstage2
+ Stage2SbInit();
+
+ //5.open hdac
+ pci_rawmodify_config32(PCI_RAWDEV(0, 0x11, 7), 0xd1, 0, 0x04);
+ printk_debug("End: init_VIA_chipset\n");
+}
+
+/**
+ * @brief Main function of the DRAM part of coreboot.
+ *
+ * Coreboot is divided into Pre-DRAM part and DRAM part.
+ *
+ *
+ * Device Enumeration:
+ * In the dev_enumerate() phase,
+ */
+
+void hardwaremain(int boot_complete)
+{
+ struct lb_memory *lb_mem;
+#if HAVE_ACPI_RESUME == 1
+ void *wake_vec;
+#endif
+
+ u16 tmp;
+ tmp = inw(VX800_ACPI_IO_BASE + 0x04);
+ acpi_sleep_type = ((tmp & (7 << 10)) >> 10) == 1 ? 3 : 0;
+
+ u8 y, x;
+ init_VIA_chipset();
+ printk_emerg("file '%s', line %d\n\n", __FILE__, __LINE__);
+
+#if 0
+
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0, 4), 0xa3, 0x80);
+ pci_rawwrite_config8(PCI_RAWDEV(0, 17, 7), 0x60, 0x20);
+ pci_rawwrite_config8(PCI_RAWDEV(0, 17, 7), 0xE5,
+ pci_rawread_config8(PCI_RAWDEV(0, 3, 0),
+ 0x88));
+#endif
+
+ pci_rawmodify_config8(PCI_RAWDEV(0, 0x11, 0), 0x51, 0x40, 0x40); //close CE-ATA (Consumer Electronics-ATA) and NFC
+
+ //pci_rawmodify_config8(PCI_RAWDEV(0, 0x11, 0), 0x50, 0x0, 0x40);//open USB Device Mode Enable
+ pci_rawmodify_config8(PCI_RAWDEV(0, 0x11, 0), 0x50, 0x40, 0x40); //close USB Device Mode
+
+ //pci_rawmodify_config8(PCI_RAWDEV(0, 0x11, 0), 0x50, 0x04, 0x04);//close USB 1.1 UHCI Port 4-5
+ //pci_rawmodify_config8(PCI_RAWDEV(0, 0x11, 0), 0x50, 0x02, 0x02);//close USB 2.0 ehci
+
+
+ //pci_rawmodify_config8(PCI_RAWDEV(0, 0x11, 0), 0x50, 0x00, 0x76);//open all usb and usb mode
+ //pci_rawmodify_config8(PCI_RAWDEV(0, 0x11, 0), 0x50, 0x76, 0x76);//close all usb
+
+ printk_info("=================SB 50h=%02x \n",
+ pci_rawread_config8(PCI_RAWDEV(0, 0x11, 0), 0x50));
+
+
+ /* FIXME: Is there a better way to handle this? */
+ init_timer();
+ printk_emerg("file '%s', line %d\n\n", __FILE__, __LINE__);
+
+ /* Find the devices we don't have hard coded knowledge about. */
+ dev_enumerate();
+ printk_emerg("file '%s', line %d\n\n", __FILE__, __LINE__);
+#if 0
+ x = y = 0;
+ printk_info("dump ehci3 \n");
+ for (; x < 16; x++) {
+ y = 0;
+ for (; y < 16; y++) {
+ printk_info("%02x ",
+ pci_rawread_config8(PCI_RAWDEV
+ (0, 0x10, 4),
+ x * 16 + y));
+ }
+ printk_info("\n");
+ }
+#endif
+
+ post_code(0x66);
+ /* Now compute and assign the bus resources. */
+ dev_configure();
+ printk_emerg("file '%s', line %d\n\n", __FILE__, __LINE__);
+#if 0
+ x = y = 0;
+ printk_info("dump ehci3 \n");
+ for (; x < 16; x++) {
+ y = 0;
+ for (; y < 16; y++) {
+ printk_info("%02x ",
+ pci_rawread_config8(PCI_RAWDEV
+ (0, 0x10, 4),
+ x * 16 + y));
+ }
+ printk_info("\n");
+ }
+#endif
+
+ post_code(0x88);
+ /* Now actually enable devices on the bus */
+ dev_enable();
+ printk_emerg("file '%s', line %d\n\n", __FILE__, __LINE__);
+ /* And of course initialize devices on the bus */
+#if 0
+ x = y = 0;
+ printk_info("dump ehci3 \n");
+ for (; x < 16; x++) {
+ y = 0;
+ for (; y < 16; y++) {
+ printk_info("%02x ",
+ pci_rawread_config8(PCI_RAWDEV
+ (0, 0x10, 4),
+ x * 16 + y));
+ }
+ printk_info("\n");
+ }
+#endif
+
+ dev_initialize();
+ post_code(0x89);
+ printk_emerg("file '%s', line %d\n\n", __FILE__, __LINE__);
+
+
+// pci_rawwrite_config16(PCI_RAWDEV(0, 0xf, 0), 0xBA, 0x0571);
+
+#if 0
+ x = y = 0;
+ printk_info("dump ehci3 \n");
+ for (; x < 16; x++) {
+ y = 0;
+ for (; y < 16; y++) {
+ printk_info("%02x ",
+ pci_rawread_config8(PCI_RAWDEV
+ (0, 0x10, 4),
+ x * 16 + y));
+ }
+ printk_info("\n");
+ }
+#endif
+
+
+#if 0
+
+ y = pci_rawread_config8(PCI_RAWDEV(0, 0xf, 0), 0x0d);
+ y &= 0x0f;
+ y |= 0x40;
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0xf, 0), 0x0d, y);
+#endif
+
+#if 0
+
+
+ static const d0f0pcitable[5] = { 0xD0, 0, 0, 0, 0xFD };
+ static const d0f2pcitable[16 * 7 + 1] = {
+ 0x88, 0xF8, 0xEF, 0x44, 0x7C, 0x24, 0x63, 0x01, 0x00, 0x09,
+ 0x00, 0x00, 0x10, 0xA2, 0x88, 0xCE,
+ 0xFF, 0x0F, 0x00, 0xAA, 0x0A, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xCC, 0x66, 0xAA, 0x55, 0x30, 0x38, 0x0C, 0x00, 0x00, 0x00,
+ 0x00, 0x22, 0x00, 0xAA, 0x00, 0x00,
+ 0x44, 0x44, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x0B, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0A, 0x01, 0x41, 0x06,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x88, 0x56, 0x70, 0x77, 0x77, 0x07, 0x77, 0x77, 0x04,
+ 0x77, 0x77, 0x77, 0x77, 0x77, 0x77,
+ 0x77, 0x77, 0x33, 0x33, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77,
+ 0x77, 0x77, 0x44, 0x44, 0x14, 0x00,
+ 0x75
+ };
+
+ static const d0f4pcitable[16 * 6 + 3] = {
+ 0x30, 0x00, 0x00,
+ 0xFF, 0xFF, 0xCC, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0xE0, 0xD6, 0x80, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x04, 0x00, 0x00, 0x04, 0x04,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x12, 0x12, 0x00, 0x00, 0x08, 0xF4,
+ 0x01, 0x01, 0x79, 0x79, 0x0A, 0x00,
+ };
+ static const d0f5pcitable[16 * 10] = {
+ 0x13, 0x0E, 0x00, 0x00, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x18, 0x9A, 0x00, 0x81, 0x28, 0xC0, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x26, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ };
+
+ static const d0f7pcitable[16 * 9] = {
+ 0x00, 0x2A, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x29, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ };
+ static const d1f0pcitable[3] = {
+ 0x01, 0x80, 0x40
+ };
+
+ static const dcf0pcitable[96] = {
+ 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0xC2, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
+ 0x40, 0x01, 0x03, 0x01, 0x7E, 0x01,
+ 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF9,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+ };
+
+ static const d10f4pcitable[48] = {
+ 0x00, 0x20, 0x43, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x9E, 0x68,
+ 0x00, 0x09, 0x13, 0x94, 0x03, 0x10,
+ 0x80, 0x60, 0x11, 0xBF, 0x00, 0xFF, 0x0F, 0x00, 0x04, 0x0B,
+ 0xCC, 0xCC, 0x00, 0xCC, 0x00, 0x00,
+ 0x20, 0x20, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x20, 0x00, 0xC0,
+ };
+
+ static const d11f0pcitable[16 * 12] = {
+ 0x44, 0x40, 0xF0, 0x0B, 0x00, 0x00, 0x00, 0x03, 0x00, 0x20,
+ 0x00, 0x00, 0x04, 0x00, 0x08, 0x00,
+ 0xC1, 0x4D, 0x19, 0x80, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00,
+ 0x00, 0x51, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x80, 0x00,
+ 0xD0, 0xFE, 0x00, 0x00, 0x00, 0x00,
+ 0x06, 0x11, 0x09, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x20, 0x84, 0x49, 0x00, 0x88, 0x00, 0x00, 0x00, 0x01, 0x08,
+ 0x1F, 0x00, 0x07, 0x1A, 0x00, 0x00,
+ 0x00, 0x6E, 0xBC, 0x88, 0x28, 0xC1, 0x10, 0x80, 0x00, 0x80,
+ 0x20, 0x88, 0x00, 0x00, 0x00, 0xAD,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x10, 0xD0, 0xFE, 0x90,
+ 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xE7, 0x03, 0xA0, 0x60, 0x20, 0xC0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ };
+
+ static const d11f7pcitable[192] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x80, 0x43,
+ 0x08, 0x80, 0x11, 0x11, 0x02, 0x0F, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80, 0x00, 0x00, 0x20, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
+ 0x82, 0xC8, 0xEE, 0x01, 0x0C, 0x0F, 0xD0, 0x48, 0x00, 0x00,
+ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x07, 0x00, 0x21, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x93, 0x08, 0x00, 0x5E, 0x00, 0x80, 0x29, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
+ };
+
+
+#define OPTION_1 1
+#define NOOPTION_1 1
+#ifdef OPTION_1
+ static const OPTION_1_d11f0pcitable[16 * 12] = {
+ 0x44, 0x80, 0xf0, 0x0b, 0x00, 0x00, 0x00, 0x03, 0x00, 0x20,
+ 0x00, 0x00, 0x04, 0x01, 0x08, 0x00,
+ 0xc0, 0x4d, 0x19, 0x80, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00,
+ 0x00, 0x53, 0x00, 0xfe, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x80, 0x00,
+ 0xd0, 0xfe, 0x00, 0x00, 0xdf, 0x00,
+ 0x06, 0x11, 0x53, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 0x84, 0x4a, 0x00, 0xda, 0x40, 0x00, 0x00, 0x01, 0x40,
+ 0x1f, 0x00, 0x07, 0x18, 0x00, 0x00,
+ 0x00, 0x2e, 0xbc, 0x00, 0x28, 0xc1, 0x10, 0x80, 0x00, 0x80,
+ 0x08, 0x88, 0x00, 0x00, 0x00, 0xad,
+ 0x06, 0x11, 0x53, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x40, 0x80, 0x40,
+ 0x00, 0x00, 0x00, 0xd3, 0xfe, 0x53,
+ 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x41, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xeb, 0x03, 0xa0, 0x60, 0x20, 0x80, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ };
+#endif
+
+
+
+ u8 i;
+/* error form ---- but add the chance to resume
+for(i=0;i<5;i++){
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0, 0), i, d0f0pcitable[i+0xcb]);
+ }
+
+
+*/
+
+/* RO reg
+for(i=0;i<5;i++){
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0, 0), i+0xcb, d0f0pcitable[i]);
+ }
+*/
+
+
+//boot ok, resume still err in linux
+#if 1
+ for (i = 0; i < 9; i++) {
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0, 2), i + 0x50,
+ d0f2pcitable[i]);
+ }
+ //9 is warm reset reg, // boot err in coreboot
+ for (i = 10; i < 64; i++) {
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0, 2), i + 0x50,
+ d0f2pcitable[i]);
+ }
+ //0x90 look d0f2 appendixA1 , if set this to 09 or 0b, then some ddr2 will crash.
+ for (i = 65; i < 113; i++) {
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0, 2), i + 0x50,
+ d0f2pcitable[i]);
+ }
+#endif
+#ifdef OPTION_1
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0, 2), 0x66, 0x09);
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0, 2), 0x70, 0xdd);
+ // pci_rawwrite_config8(PCI_RAWDEV(0, 0, 2), 0x90, 0x09);
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0, 2), 0x92, 0x40);
+
+#endif
+
+
+
+#if 1
+
+
+//d0f3
+/* */
+ // pci_rawwrite_config8(PCI_RAWDEV(0, 0, 3), 0x86, 0x3b); setting, my lspci is 0x29
+ //set bit4 cause the ide not be found
+// pci_rawwrite_config8(PCI_RAWDEV(0, 0, 3), 0x86, 0x2b);
+ //set bit1 cause the ide not be found
+
+// pci_rawwrite_config8(PCI_RAWDEV(0, 0, 3), 0x86, 0x29);
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0, 3), 0x95, 0x05);
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0, 3), 0x99, 0x12);
+
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0, 3), 0xde, 0x00);
+#endif
+
+//boot ok, resume err in coreboot
+#if 1
+ for (i = 0; i < 99; i++) {
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0, 4), i + 0x8d,
+ d0f4pcitable[i]);
+ }
+#endif
+
+#ifdef OPTION_1
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0, 4), 0xe9, 0x90);
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0, 4), 0xec, 0x0);
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0, 4), 0xed, 0x0);
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0, 4), 0xee, 0x0);
+#endif
+
+
+#if 1
+//boot ok, resume still err in linux
+ for (i = 0; i < 160; i++) {
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0, 5), i + 0x60,
+ d0f5pcitable[i]);
+ }
+ for (i = 0; i < 144; i++) {
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0, 7), i + 0x60,
+ d0f7pcitable[i]);
+ }
+ for (i = 0; i < 3; i++) {
+ pci_rawwrite_config8(PCI_RAWDEV(0, 1, 0), i + 0xb0,
+ d1f0pcitable[i]);
+ }
+ for (i = 0; i < 96; i++) {
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0xc, 0), i + 0x40,
+ dcf0pcitable[i]);
+ }
+#endif
+
+#ifdef OPTION_1
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0, 7), 0x61, 0x0);
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0, 7), 0x63, 0x0);
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0, 7), 0x76, 0xd0);
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0xc, 0), 0x88, 0x81);
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0xc, 0), 0x89, 0x01);
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0xc, 0), 0x8A, 0x60);
+#endif
+
+//d15f0
+
+
+
+
+#if 1
+
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0x10, 0), 0x4a, 0xa2); // no affect.
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0x10, 1), 0x4a, 0xa2);
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0x10, 2), 0x4a, 0xa2);
+
+//boot ok, resume still err in linux, and if disable USB, then all ok
+// for(i=0;i<48;i++){
+ for (i = 0; i < 44; i++) {
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0x10, 4), i + 0x40,
+ d10f4pcitable[i]);
+ }
+#endif
+
+//#ifdef NOOPTION_1
+#if 0
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0x10, 4), 0x6b, 0x01);
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0x10, 4), 0x6d, 0x00);
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0x10, 4), 0x6e, 0x08);
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0x10, 4), 0x6f, 0x80);
+#endif
+
+
+
+#if 1
+//before (11.0)is add, s3 resume has already always dead in first resume(more frequenly), and sleep ok
+// for(i=0;i<192;i++){
+ for (i = 0; i < 6; i++) {
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0x11, 0), i + 0x40,
+ d11f0pcitable[i]);
+ }
+ //6 is uart and dvp vcp, will have // HAVE no com1 ,and no gui show,textmode ok ,s3 sleep ok, resume fail
+
+ //7-18 is my familar part
+ for (i = 7; i < 18; i++) { //sleep ok ,resume sleep err 2
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0x11, 0), i + 0x40,
+ d11f0pcitable[i]);
+ }
+
+
+ for (i = 18; i < 21; i++) { //sleep ok , sleep err 1, resume
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0x11, 0), i + 0x40,
+ d11f0pcitable[i]);
+ }
+ //0x55 56 57 irq intA#B#C# linkA#linkB#linkC#
+ for (i = 24; i < 27; i++) { //sleep ok , resume sleep err 1 resume 1
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0x11, 0), i + 0x40,
+ d11f0pcitable[i]);
+ }
+ //5b port 80h
+ pci_rawmodify_config8(PCI_RAWDEV(0, 0x11, 0), 0x5b, 0x0, 0x08);
+ // i++;
+ // pci_rawwrite_config8(PCI_RAWDEV(0, 0x11, 0), i+0x40, d11f0pcitable[i]);
+
+ for (i = 28; i < 72; i++) { //sleep ok , resume sleep err 1 , resume 1ci
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0x11, 0), i + 0x40,
+ d11f0pcitable[i]);
+ }
+ //7273ACPI BASE
+
+ for (i = 74; i < 112; i++) { //boot ok, resume still err in linux
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0x11, 0), i + 0x40,
+ d11f0pcitable[i]);
+ }
+
+ //B0B4B5 dvp vcp, if copy this ,then no uart, no gui(of unbuntu)
+ // pci_rawwrite_config8(PCI_RAWDEV(0, 0x11, 0), 0xb0, d11f0pcitable[112]);
+ i = pci_rawread_config8(PCI_RAWDEV(0, 17, 0), 0xB0);
+ //multiplex with VCP
+ // i = i | 0x30;
+ i = i & 0xf7;
+ pci_rawwrite_config8(PCI_RAWDEV(0, 17, 0), 0xB0, i);
+
+
+
+ for (i = 113; i < 114; i++) { //boot ok, resume still err in linux
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0x11, 0), i + 0x40,
+ d11f0pcitable[i]);
+ }
+
+ for (i = 115; i < 116; i++) { //boot ok, resume still err in linux
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0x11, 0), i + 0x40,
+ d11f0pcitable[i]);
+ }
+
+
+ for (i = 118; i < 192; i++) { //boot ok, resume still err in linux
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0x11, 0), i + 0x40,
+ d11f0pcitable[i]);
+ }
+#endif
+#ifdef NOOPTION_1
+// for(i=0;i<192;i++){
+ for (i = 0; i < 6; i++) {
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0x11, 0), i + 0x40,
+ OPTION_1_d11f0pcitable[i]);
+ }
+ //6 is uart and dvp vcp, will have // HAVE no com1 ,and no gui show,textmode ok ,s3 sleep ok, resume fail
+
+ //7-18 is my familar part
+ for (i = 7; i < 18; i++) { // sleep err 2
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0x11, 0), i + 0x40,
+ OPTION_1_d11f0pcitable[i]);
+ }
+
+ for (i = 18; i < 21; i++) { //sleep ok , resume ???
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0x11, 0), i + 0x40,
+ d11f0pcitable[i]);
+ }
+ //0x55 56 57 irq intA#B#C# linkA#linkB#linkC#
+ for (i = 24; i < 27; i++) { //sleep ok , resume ???
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0x11, 0), i + 0x40,
+ d11f0pcitable[i]);
+ }
+ //5b port 80h
+ i++;
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0x11, 0), i + 0x40,
+ OPTION_1_d11f0pcitable[i]);
+
+ for (i = 28; i < 72; i++) { //sleep ok , resume???
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0x11, 0), i + 0x40,
+ OPTION_1_d11f0pcitable[i]);
+ }
+ //7273ACPI BASE
+
+ for (i = 74; i < 112; i++) { //boot ok, resume still err in linux
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0x11, 0), i + 0x40,
+ OPTION_1_d11f0pcitable[i]);
+ }
+
+ //B0B4B5 dvp vcp, if copy this ,then no uart, no gui(of unbuntu)
+ // pci_rawwrite_config8(PCI_RAWDEV(0, 0x11, 0), 0xb0, OPTION_1_d11f0pcitable[112]);
+ i = pci_rawread_config8(PCI_RAWDEV(0, 17, 0), 0xB0);
+ //multiplex with VCP
+ // i = i | 0x30;
+ i = i & 0xf7;
+ pci_rawwrite_config8(PCI_RAWDEV(0, 17, 0), 0xB0, i);
+
+
+
+ for (i = 113; i < 114; i++) { //boot ok, resume still err in linux
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0x11, 0), i + 0x40,
+ OPTION_1_d11f0pcitable[i]);
+ }
+
+ for (i = 115; i < 116; i++) { //boot ok, resume still err in linux
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0x11, 0), i + 0x40,
+ OPTION_1_d11f0pcitable[i]);
+ }
+
+ for (i = 118; i < 192; i++) { //boot ok, resume still err in linux
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0x11, 0), i + 0x40,
+ OPTION_1_d11f0pcitable[i]);
+ }
+#endif
+
+#if 1
+ pci_rawwrite_config16(PCI_RAWDEV(0, 0xf, 0), 0xBA, PCI_DEVICE_ID_VIA_VX855_IDE); //5324
+ pci_rawwrite_config16(PCI_RAWDEV(0, 0xf, 0), 0xBE,
+ PCI_DEVICE_ID_VIA_VX855_IDE);
+ pci_rawwrite_config16(PCI_RAWDEV(0, 0x11, 0), 0xA0,
+ PCI_VENDOR_ID_VIA);
+ pci_rawwrite_config16(PCI_RAWDEV(0, 0x11, 0), 0xA2, PCI_DEVICE_ID_VIA_VX855_LPC); //8353
+ i = pci_rawread_config8(PCI_RAWDEV(0, 0x11, 0), 0x79);
+ i &= ~0x40;
+ i |= 0x40;
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0x11, 0), 0x79, i);
+ pci_rawwrite_config16(PCI_RAWDEV(0, 0x11, 0), 0x72,
+ PCI_DEVICE_ID_VIA_VX855_LPC);
+
+
+//boot ok, resume still err in linux
+ for (i = 0; i < 192; i++) {
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0x11, 7), i + 0x40,
+ d11f7pcitable[i]);
+ }
+#endif
+#ifdef OPTION_1
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0x11, 7), 0x61, 0x2a);
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0x11, 7), 0x63, 0xa0);
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0x11, 7), 0x64, 0xaa);
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0x11, 7), 0x84, 0x0);
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0x11, 7), 0x88, 0x02);
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0x11, 7), 0xe6, 0x3f);
+#endif
+
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0x14, 0), 0x40, 0x20);
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0x14, 0), 0x41, 0x31);
+
+
+
+#ifdef OPTION_1
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0x14, 0), 0x40, 0x00);
+#endif
+
+
+#endif
+
+ u8 i911;
+ //disable CHB L.L
+ //set VGA memory selection
+ i911 = pci_rawread_config8(PCI_RAWDEV(0, 0x1, 0), 0xb0);
+ i911 &= 0xF8;
+ //ByteVal |= 0x03;
+ i911 |= 0x01;
+ pci_rawwrite_config8(PCI_RAWDEV(0, 0x1, 0), 0xb0, i911);
+
+
+#if 1
+ struct device *dev;
+ printk_info("=========zjldump all devices...\n");
+ for (dev = all_devices; dev; dev = dev->next) {
+ if (dev->path.type == DEVICE_PATH_PCI) {
+ printk_debug("%s dump\n", dev_path(dev));
+ x = y = 0;
+ for (; x < 16; x++) {
+ y = 0;
+ for (; y < 16; y++) {
+ printk_info("%02x ",
+ pci_read_config8(dev,
+ x *
+ 16 +
+ y));
+ }
+ printk_info("\n");
+ }
+
+ }
+ printk_info("\n");
+ }
+#endif
+
+
+
+
+ //pci_rawmodify_config8(PCI_RAWDEV(0, 0x10, 4), 0x04, 0x17, 0x17);//
+// pci_rawmodify_config8(PCI_RAWDEV(0, 0x10, 4), 0x0c, 0x08, 0xff);///
+
+
+
+}
diff --git a/src/northbridge/via/vx800/northbridge.c b/src/northbridge/via/vx800/northbridge.c
new file mode 100644
index 0000000000..3d855ec4b5
--- /dev/null
+++ b/src/northbridge/via/vx800/northbridge.c
@@ -0,0 +1,247 @@
+/*
+ * 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
+ */
+
+/*
+ part of this file is from cx700 port, part of is from cn700 port,
+ */
+
+#include <console/console.h>
+#include <arch/io.h>
+#include <stdint.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <stdlib.h>
+#include <string.h>
+#include <bitops.h>
+#include <cpu/cpu.h>
+#include "chip.h"
+#include "northbridge.h"
+#include "vx800.h"
+
+static void memctrl_init(device_t dev)
+{
+/*
+ set VGA in UMARamSetting.c, not in this function.
+*/
+#if 0
+ pci_write_config8(dev, 0x85, 0x20);
+ pci_write_config8(dev, 0x86, 0x2d);
+
+ /* Set up VGA timers */
+ pci_write_config8(dev, 0xa2, 0x44);
+
+ /* Enable VGA with a 32mb framebuffer */
+ pci_write_config16(dev, 0xa0, 0xd000);
+
+ pci_write_config16(dev, 0xa4, 0x0010);
+
+ //b0: 60 aa aa 5a 0f 00 00 00 08
+ pci_write_config16(dev, 0xb0, 0xaa00);
+ pci_write_config8(dev, 0xb8, 0x08);
+#endif
+}
+
+static const struct device_operations memctrl_operations = {
+ .read_resources = vx800_noop,
+ .init = memctrl_init,
+};
+
+static const struct pci_driver memctrl_driver __pci_driver = {
+ .ops = &memctrl_operations,
+ .vendor = PCI_VENDOR_ID_VIA,
+ .device = PCI_DEVICE_ID_VIA_VX855_MEMCTRL,
+};
+
+static void pci_domain_read_resources(device_t dev)
+{
+ struct resource *resource;
+
+ printk_spew("Entering vx800 pci_domain_read_resources.\n");
+
+ /* Initialize the system wide io space constraints */
+ resource = new_resource(dev, IOINDEX_SUBTRACTIVE(0, 0));
+ resource->limit = 0xffffUL;
+ resource->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE |
+ IORESOURCE_ASSIGNED;
+
+ /* Initialize the system wide memory resources constraints */
+ resource = new_resource(dev, IOINDEX_SUBTRACTIVE(1, 0));
+ resource->limit = 0xffffffffULL;
+ resource->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE |
+ IORESOURCE_ASSIGNED;
+
+ printk_spew("Leaving vx800 pci_domain_read_resources.\n");
+}
+
+static void ram_resource(device_t dev, unsigned long index,
+ unsigned long basek, unsigned long sizek)
+{
+ struct resource *resource;
+
+ if (!sizek) {
+ return;
+ }
+ resource = new_resource(dev, index);
+ resource->base = ((resource_t) basek) << 10;
+ resource->size = ((resource_t) sizek) << 10;
+ resource->flags = IORESOURCE_MEM | IORESOURCE_CACHEABLE |
+ IORESOURCE_FIXED | IORESOURCE_STORED | IORESOURCE_ASSIGNED;
+}
+
+static void tolm_test(void *gp, struct device *dev, struct resource *new)
+{
+ struct resource **best_p = gp;
+ struct resource *best;
+ best = *best_p;
+ if (!best || (best->base > new->base)) {
+ best = new;
+ }
+ *best_p = best;
+}
+
+static u32 find_pci_tolm(struct bus *bus)
+{
+ print_debug("Entering find_pci_tolm\n");
+ struct resource *min;
+ u32 tolm;
+ min = 0;
+ search_bus_resources(bus, IORESOURCE_MEM, IORESOURCE_MEM,
+ tolm_test, &min);
+ tolm = 0xffffffffUL;
+ if (min && tolm > min->base) {
+ tolm = min->base;
+ }
+ print_debug("Leaving find_pci_tolm\n");
+ return tolm;
+}
+
+static void pci_domain_set_resources(device_t dev)
+{
+ /*
+ * the order is important to find the correct ram size.
+ */
+ u8 ramregs[] = { 0x43, 0x42, 0x41, 0x40 };
+ device_t mc_dev;
+ u32 pci_tolm;
+ u8 reg;
+
+ printk_spew("Entering vx800 pci_domain_set_resources.\n");
+
+ pci_tolm = find_pci_tolm(&dev->link[0]);
+ mc_dev = dev_find_device(PCI_VENDOR_ID_VIA,
+ PCI_DEVICE_ID_VIA_VX855_MEMCTRL, 0);
+
+ if (mc_dev) {
+ unsigned long tomk, tolmk;
+ unsigned char rambits;
+ u8 i, idx;
+
+ /*
+ * once the register value is not zero, the ramsize is
+ * this register's value multiply 64 * 1024 * 1024
+ */
+ for (rambits = 0, i = 0; i < ARRAY_SIZE(ramregs); i++) {
+ unsigned char reg;
+ rambits = pci_read_config8(mc_dev, ramregs[i]);
+ if (rambits != 0)
+ break;
+ }
+/*
+Get memory size and frame buffer from northbridge's registers.
+if register with invalid value we set frame buffer size to 32M for default, but it won't happen.
+*/
+ reg = pci_read_config8(mc_dev, 0xa1);
+ reg &= 0x70;
+ reg = reg >> 4;
+ /* TOP 1M SM Memory */
+ if (reg == 0x0)
+ tomk = (((rambits << 6) - 32 - VIACONFIG_TOP_SM_SIZE_MB) * 1024); // Set frame buffer 32M for default
+ else
+ tomk =
+ (((rambits << 6) - (4 << reg) -
+ VIACONFIG_TOP_SM_SIZE_MB) * 1024);
+
+ printk_spew("tomk is 0x%x\n", tomk);
+ /* Compute the Top Of Low Memory, in Kb */
+ tolmk = pci_tolm >> 10;
+ if (tolmk >= tomk) {
+ /* The PCI hole does does not overlap the memory. */
+ tolmk = tomk;
+ }
+ /* Report the memory regions */
+ idx = 10;
+ /* TODO: Hole needed? */
+ ram_resource(dev, idx++, 0, 640); /* first 640k */
+ /* Leave a hole for vga, 0xa0000 - 0xc0000 */
+ ram_resource(dev, idx++, 768, (tolmk - 768));
+ }
+ assign_resources(&dev->link[0]);
+}
+
+static unsigned int pci_domain_scan_bus(device_t dev, unsigned int max)
+{
+ printk_debug("Entering vx800 pci_domain_scan_bus.\n");
+
+ max = pci_scan_bus(&dev->link[0], PCI_DEVFN(0, 0), 0xff, max);
+ return max;
+}
+
+static const struct device_operations pci_domain_ops = {
+ .read_resources = pci_domain_read_resources,
+ .set_resources = pci_domain_set_resources,
+ .enable_resources = enable_childrens_resources,
+ .init = 0,
+ .scan_bus = pci_domain_scan_bus,
+};
+
+static void cpu_bus_init(device_t dev)
+{
+ initialize_cpus(&dev->link[0]);
+}
+
+static void cpu_bus_noop(device_t dev)
+{
+}
+
+static const struct device_operations cpu_bus_ops = {
+ .read_resources = cpu_bus_noop,
+ .set_resources = cpu_bus_noop,
+ .enable_resources = cpu_bus_noop,
+ .init = cpu_bus_init,
+ .scan_bus = 0,
+};
+
+static void enable_dev(struct device *dev)
+{
+ printk_spew("In VX800 enable_dev for device %s.\n", dev_path(dev));
+
+ /* Set the operations if it is a special bus type */
+ if (dev->path.type == DEVICE_PATH_PCI_DOMAIN) {
+ dev->ops = &pci_domain_ops;
+ pci_set_method(dev);
+ } else if (dev->path.type == DEVICE_PATH_APIC_CLUSTER) {
+ dev->ops = &cpu_bus_ops;
+ }
+}
+
+struct chip_operations northbridge_via_vx800_ops = {
+ CHIP_NAME("VIA VX800 Chipset")
+ .enable_dev = enable_dev,
+};
diff --git a/src/northbridge/via/vx800/northbridge.h b/src/northbridge/via/vx800/northbridge.h
new file mode 100644
index 0000000000..577efe6291
--- /dev/null
+++ b/src/northbridge/via/vx800/northbridge.h
@@ -0,0 +1,25 @@
+/*
+ * 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
+ */
+
+#ifndef NORTHBRIDGE_VIA_VX800_H
+#define NORTHBRIDGE_VIA_VX800_H
+
+extern unsigned int vx800_scan_root_bus(device_t root, unsigned int max);
+
+#endif /* NORTHBRIDGE_VIA_VX800_H */
diff --git a/src/northbridge/via/vx800/raminit.c b/src/northbridge/via/vx800/raminit.c
new file mode 100644
index 0000000000..58aef2561e
--- /dev/null
+++ b/src/northbridge/via/vx800/raminit.c
@@ -0,0 +1,74 @@
+/*
+ * 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
+ */
+
+#include <spd.h>
+#include <sdram_mode.h>
+#include <delay.h>
+#include <arch/pci_rawops.h>
+
+#define DEBUG_RAM_SETUP 1
+
+
+#ifdef DEBUG_RAM_SETUP
+#define PRINT_DEBUG_MEM(x) print_debug(x)
+#define PRINT_DEBUG_MEM_HEX8(x) print_debug_hex8(x)
+#define PRINT_DEBUG_MEM_HEX16(x) print_debug_hex16(x)
+#define PRINT_DEBUG_MEM_HEX32(x) print_debug_hex32(x)
+#define DUMPNORTH() dump_pci_device(PCI_DEV(0, 0, 0))
+#else
+#define PRINT_DEBUG_MEM(x)
+#define PRINT_DEBUG_MEM_HEX8(x)
+#define PRINT_DEBUG_MEM_HEX16(x)
+#define PRINT_DEBUG_MEM_HEX32(x)
+#define DUMPNORTH()
+#endif
+#include "northbridge/via/vx800/ddr2init/Translatorddr2init.c"
+#include "northbridge/via/vx800/ddr2init/DramInit.h"
+#include "northbridge/via/vx800/vx800_early_smbus.c"
+#include "northbridge/via/vx800/vx800_early_serial.c"
+#include "northbridge/via/vx800/ddr2init/DramUtil.h"
+#include "northbridge/via/vx800/ddr2init/DramUtil.c"
+#include "northbridge/via/vx800/ddr2init/vx800/Detection.c"
+#include "northbridge/via/vx800/ddr2init/vx800/FreqSetting.c"
+#include "northbridge/via/vx800/ddr2init/vx800/TimingSetting.c"
+#include "northbridge/via/vx800/ddr2init/vx800/DRDY_BL.c"
+#include "northbridge/via/vx800/ddr2init/vx800/DrivingSetting.c"
+#include "northbridge/via/vx800/ddr2init/vx800/ClkCtrl.c"
+#include "northbridge/via/vx800/ddr2init/vx800/DevInit.c"
+#include "northbridge/via/vx800/ddr2init/vx800/RankMap.c"
+#include "northbridge/via/vx800/ddr2init/vx800/DQSSearch.c"
+#include "northbridge/via/vx800/ddr2init/vx800/FinalSetting.c"
+#include "northbridge/via/vx800/ddr2init/vx800/UMARamSetting.c"
+#include "northbridge/via/vx800/ddr2init/DramInit.c"
+/*
+ * Support one dimm with up to 2 ranks
+ */
+
+static void ddr2_ram_setup()
+{
+ u8 Data;
+ CB_STATUS Status;
+ PRINT_DEBUG_MEM("In ddr2_ram_setup\r");
+
+ Status = DDR2_DRAM_INIT();
+ if (CB_SUCCESS != Status) {
+ PRINT_DEBUG_MEM("Dram init error. Status = %x\r");
+ }
+
+}
diff --git a/src/northbridge/via/vx800/raminit.h b/src/northbridge/via/vx800/raminit.h
new file mode 100644
index 0000000000..7885aa7dd2
--- /dev/null
+++ b/src/northbridge/via/vx800/raminit.h
@@ -0,0 +1,24 @@
+/*
+ * 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
+ */
+
+#ifndef RAMINIT_H
+#define RAMINIT_H
+
+#define MEMCTRL PCI_DEV(0,0,3)
+#endif /* RAMINIT_H */
diff --git a/src/northbridge/via/vx800/romstrap.inc b/src/northbridge/via/vx800/romstrap.inc
new file mode 100644
index 0000000000..76c5e46d88
--- /dev/null
+++ b/src/northbridge/via/vx800/romstrap.inc
@@ -0,0 +1,51 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2004 Tyan Computer
+ * (Written by Yinghai Lu <yhlu@tyan.com> for Tyan Computer)
+ * Copyright (C) 2007 Rudolf Marek <r.marek@assembler.cz>
+ * 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
+ */
+
+/* This file constructs the ROM strap table for K8T890 and K8M890 */
+
+ .section ".romstrap", "a", @progbits
+
+ .globl __romstrap_start
+__romstrap_start:
+tblpointer:
+ .long 0x55aa66cc
+ .long 0x88012554
+ .long 0x77107777
+ .long 0x00770814
+
+
+ .long 0x00000000
+ .long 0x00000000
+ .long 0x00000000
+ .long 0x00000000
+
+/*
+ * The pointer to above table should be at 0xffffffd0,
+ * the table itself MUST be aligned to 128B it seems!
+ */
+rspointers:
+ .long tblpointer // It will be 0xffffffd0
+
+ .globl __romstrap_end
+
+__romstrap_end:
+.previous
diff --git a/src/northbridge/via/vx800/romstrap.lds b/src/northbridge/via/vx800/romstrap.lds
new file mode 100644
index 0000000000..2e300c95a5
--- /dev/null
+++ b/src/northbridge/via/vx800/romstrap.lds
@@ -0,0 +1,26 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007 AMD
+ * (Written by Yinghai Lu <yinghai.lu@amd.com> for AMD)
+ *
+ * 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
+ */
+
+SECTIONS {
+ . = (_ROMBASE + ROM_IMAGE_SIZE - 0x2c) - (__romstrap_end - __romstrap_start);
+ .romstrap (.): {
+ *(.romstrap)
+ }
+}
diff --git a/src/northbridge/via/vx800/vga.c b/src/northbridge/via/vx800/vga.c
new file mode 100644
index 0000000000..03680786e5
--- /dev/null
+++ b/src/northbridge/via/vx800/vga.c
@@ -0,0 +1,148 @@
+/*
+ * 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
+ */
+
+/* Note: Some of the VGA control registers are located on the memory controller.
+ Registers are set both in raminit.c and northbridge.c */
+
+#include <console/console.h>
+#include <arch/io.h>
+#include <stdint.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <stdlib.h>
+#include <string.h>
+#include <bitops.h>
+#include <cpu/cpu.h>
+#include <cpu/x86/mtrr.h>
+#include <cpu/x86/msr.h>
+#include "chip.h"
+#include "northbridge.h"
+#include "vgachip.h"
+
+/* PCI Domain 1 Device 0 Function 0 */
+
+#define SR_INDEX 0x3c4
+#define SR_DATA 0x3c5
+#define CRTM_INDEX 0x3b4
+#define CRTM_DATA 0x3b5
+#define CRTC_INDEX 0x3d4
+#define CRTC_DATA 0x3d5
+
+void write_protect_vgabios(void)
+{
+ device_t dev;
+
+ printk_info("write_protect_vgabios\n");
+ /* there are two possible devices. Just do both. */
+ dev =
+ dev_find_device(PCI_VENDOR_ID_VIA,
+ PCI_DEVICE_ID_VIA_VX855_MEMCTRL, 0);
+ if (dev)
+ pci_write_config8(dev, 0x80, 0xff);
+ /*vx855 no th 0x61 reg */
+ /*dev = dev_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX855_NB_VLINK, 0);
+ //if(dev)
+ // pci_write_config8(dev, 0x61, 0xff); */
+}
+
+extern u8 acpi_sleep_type;
+static void vga_init(device_t dev)
+{
+ uint8_t reg8;
+
+ print_debug("Initiailizing VGA...\n");
+ u8 tmp8;
+//A20 OPEN
+ tmp8 = inb(0x92);
+ tmp8 = tmp8 | 2;
+ outb(tmp8, 0x92);
+
+ //*
+ //pci_write_config8(dev, 0x04, 0x07);
+ //pci_write_config32(dev,0x10, 0xa0000008);
+ //pci_write_config32(dev,0x14, 0xdd000000);
+ pci_write_config32(dev, 0x10, VIACONFIG_VGA_PCI_10);
+ pci_write_config32(dev, 0x14, VIACONFIG_VGA_PCI_14);
+ pci_write_config8(dev, 0x3c, 0x0a); //same with vx855_lpc.c
+ //*/
+ printk_emerg("file '%s', line %d\n\n", __FILE__, __LINE__);
+
+
+#if 1
+ printk_debug("INSTALL REAL-MODE IDT\n");
+ setup_realmode_idt();
+ printk_debug("DO THE VGA BIOS\n");
+
+ do_vgabios();
+ if ((acpi_sleep_type == 3) || (PAYLOAD_IS_SEABIOS == 0)) {
+ printk_debug("Enable VGA console\n");
+ // remove this function since in cn700 it is said "VGA seems to work without this, but crash & burn with it"
+ //but the existense of vga_enable_console() seems do not hurt my coreboot. XP+ubuntu s3 can resume with and without this function.
+ //and remove it also do not help my s3 problem: desktop screen have some thin black line, after resuming back to win.
+ vga_enable_console();
+ }
+#else
+/* Attempt to manually force the rom to load */
+ printk_debug("Forcing rom load\r\n");
+ pci_rom_load(dev, 0xfff80000);
+ run_bios(dev, 0xc0000);
+#endif
+ if ((acpi_sleep_type == 3) || (PAYLOAD_IS_SEABIOS == 0)) {
+ /* It's not clear if these need to be programmed before or after
+ * the VGA bios runs. Try both, clean up later */
+ /* Set memory rate to 200MHz */
+ outb(0x3d, CRTM_INDEX);
+ reg8 = inb(CRTM_DATA);
+ reg8 &= 0x0f;
+ reg8 |= (0x3 << 4);
+ outb(0x3d, CRTM_INDEX);
+ outb(reg8, CRTM_DATA);
+
+ /* Set framebuffer size to CONFIG_VIDEO_MB mb */
+ /*reg8 = (CONFIG_VIDEO_MB/4);
+ outb(0x39, SR_INDEX);
+ outb(reg8, SR_DATA); */
+ }
+ printk_emerg("file '%s', line %d\n\n", __FILE__, __LINE__);
+
+}
+
+static void vga_read_resources(device_t dev)
+{
+ dev->rom_address = (void *) (0xffffffff - FULL_ROM_SIZE + 1);
+ dev->on_mainboard = 1;
+ pci_dev_read_resources(dev);
+}
+
+
+static struct device_operations vga_operations = {
+ .read_resources = vga_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .init = vga_init,
+ .ops_pci = 0,
+};
+
+
+static const struct pci_driver vga_driver __pci_driver = {
+ .ops = &vga_operations,
+ .vendor = PCI_VENDOR_ID_VIA,
+ .device = PCI_DEVICE_ID_VIA_VX855_VGA,
+};
diff --git a/src/northbridge/via/vx800/vgabios.c b/src/northbridge/via/vx800/vgabios.c
new file mode 100644
index 0000000000..6155a79581
--- /dev/null
+++ b/src/northbridge/via/vx800/vgabios.c
@@ -0,0 +1,862 @@
+#include <console/console.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#undef __KERNEL__
+#include <arch/io.h>
+#include <string.h>
+#include "vgachip.h"
+
+
+/* vgabios.c. Derived from: */
+
+/*------------------------------------------------------------ -*- C -*-
+ * 2 Kernel Monte a.k.a. Linux loading Linux on x86
+ *
+ * Erik Arjan Hendriks <hendriks@lanl.gov>
+ *
+ * This version is a derivative of the original two kernel monte
+ * which is (C) 2000 Scyld.
+ *
+ * Copyright (C) 2000 Scyld Computing Corporation
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Portions related to the alpha architecture are:
+ *
+ * Copyright(C) 2001 University of California. LA-CC Number 01-67.
+ * This software has been authored by an employee or employees of the
+ * University of California, operator of the Los Alamos National
+ * Laboratory under Contract No. W-7405-ENG-36 with the U.S.
+ * Department of Energy. The U.S. Government has rights to use,
+ * reproduce, and distribute this software. If the software is
+ * modified to produce derivative works, such modified software should
+ * be clearly marked, so as not to confuse it with the version
+ * available from LANL.
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by
+ * reference to http://www.gnu.org/licenses/gpl.html.
+ *
+ * This software is provided by the author(s) "as is" and any express
+ * or implied warranties, including, but not limited to, the implied
+ * warranties of merchantability and fitness for a particular purpose
+ * are disclaimed. In no event shall the author(s) be liable for any
+ * direct, indirect, incidental, special, exemplary, or consequential
+ * damages (including, but not limited to, procurement of substitute
+ * goods or services; loss of use, data, or profits; or business
+ * interruption) however caused and on any theory of liability,
+ * whether in contract, strict liability, or tort (including
+ * negligence or otherwise) arising in any way out of the use of this
+ * software, even if advised of the possibility of such damage.
+ *
+ * $Id: vgabios.c,v 1.5 2004/10/06 17:33:52 rminnich Exp $
+ *--------------------------------------------------------------------*/
+
+/* Modified to be a self sufficient plug in so that it can be used
+ without reliance on other parts of coreboot's core
+ (C) 2005 Nick.Barker9@btinternet.com
+
+ Used initially for epia-m where there are problems getting the bios
+ emulator to successfully run this bios.
+*/
+/* Declare a temporary global descriptor table - necessary because the
+ Core part of the bios no longer sets up any 16 bit segments */
+__asm__(
+ /* pointer to original gdt */
+ "gdtarg: \n"
+ " .word gdt_limit \n"
+ " .long gdt \n"
+ /* compute the table limit */
+ "__mygdt_limit = __mygdt_end - __mygdt - 1 \n"
+ "__mygdtaddr: \n"
+ " .word __mygdt_limit \n"
+ " .long __mygdt \n"
+ "__mygdt: \n"
+ /* selgdt 0, unused */
+ " .word 0x0000, 0x0000 \n"
+ " .byte 0x00, 0x00, 0x00, 0x00 \n"
+ /* selgdt 8, unused */
+ " .word 0x0000, 0x0000 \n"
+ " .byte 0x00, 0x00, 0x00, 0x00 \n"
+ /* selgdt 0x10, flat code segment */
+ " .word 0xffff, 0x0000 \n"
+ " .byte 0x00, 0x9b, 0xcf, 0x00 \n"
+ /* selgdt 0x18, flat data segment */
+ " .word 0xffff, 0x0000 \n"
+ " .byte 0x00, 0x93, 0xcf, 0x00 \n"
+ /* selgdt 0x20, unused */
+ " .word 0x0000, 0x0000 \n"
+ " .byte 0x00, 0x00, 0x00, 0x00 \n"
+ /* selgdt 0x28 16-bit 64k code at 0x00000000 */
+ " .word 0xffff, 0x0000 \n"
+ " .byte 0, 0x9a, 0, 0 \n"
+ /* selgdt 0x30 16-bit 64k data at 0x00000000 */
+ " .word 0xffff, 0x0000 \n"
+ " .byte 0, 0x92, 0, 0 \n"
+ "__mygdt_end: \n");
+
+/* Declare a pointer to where our idt is going to be i.e. at mem zero */
+__asm__("__myidt: \n"
+ /* 16-bit limit */
+ " .word 1023 \n"
+ /* 24-bit base */
+ " .long 0 \n" " .word 0 \n");
+
+/* The address arguments to this function are PHYSICAL ADDRESSES */
+extern u8 acpi_sleep_type;
+
+static void real_mode_switch_call_vga(unsigned long devfn)
+{
+ if ((acpi_sleep_type == 0) && (PAYLOAD_IS_SEABIOS == 1))
+ return;
+ __asm__ __volatile__(
+ // paranoia -- does ecx get saved? not sure. This is
+ // the easiest safe thing to do.
+ " pushal \n"
+ /* save the stack */
+ " mov %esp, __stack \n"
+ " jmp 1f \n"
+ "__stack: .long 0 \n" "1:\n"
+ /* get devfn into %ecx */
+ " movl %esp, %ebp \n"
+ " movl 8(%ebp), %ecx \n"
+ /* load 'our' gdt */
+ " lgdt %cs:__mygdtaddr \n"
+ /* This configures CS properly for real mode. */
+ " ljmp $0x28, $__rms_16bit\n"
+ "__rms_16bit: \n"
+ " .code16 \n"
+ /* 16 bit code from here on... */
+ /* Load the segment registers w/ properly configured segment
+ * descriptors. They will retain these configurations (limits,
+ * writability, etc.) once protected mode is turned off. */
+ " mov $0x30, %ax \n"
+ " mov %ax, %ds \n"
+ " mov %ax, %es \n"
+ " mov %ax, %fs \n"
+ " mov %ax, %gs \n"
+ " mov %ax, %ss \n"
+ /* Turn off protection (bit 0 in CR0) */
+ " movl %cr0, %eax \n"
+ " andl $0xFFFFFFFE, %eax \n"
+ " movl %eax, %cr0 \n"
+ /* Now really going into real mode */
+ " ljmp $0, $__rms_real\n"
+ "__rms_real: \n"
+ /* put the stack at the end of page zero.
+ * that way we can easily share it between real and protected,
+ * since the 16-bit ESP at segment 0 will work for any case.
+ /* Setup a stack */
+ " mov $0x0, %ax \n"
+ " mov %ax, %ss \n"
+ " movl $0x1000, %eax \n"
+ " movl %eax, %esp \n"
+ /* Load our 16 it idt */
+ " xor %ax, %ax \n"
+ " mov %ax, %ds \n"
+ " lidt __myidt \n"
+ /* Dump zeros in the other segregs */
+ " mov %ax, %es \n"
+ " mov %ax, %fs \n"
+ " mov %ax, %gs \n"
+ " mov $0x40, %ax \n"
+ " mov %ax, %ds \n"
+ " mov %cx, %ax \n"
+ /* run VGA BIOS at 0xc000:0003 */
+ " lcall $0xc000, $0x0003\n"
+ /* if we got here, just about done.
+ * Need to get back to protected mode */
+ " movl %cr0, %eax \n" " orl $0x0000001, %eax\n" /* PE = 1 */
+ " movl %eax, %cr0 \n"
+ /* Now that we are in protected mode jump to a 32 bit code segment. */
+ " data32 ljmp $0x10, $vgarestart\n"
+ "vgarestart:\n"
+ " .code32\n"
+ " movw $0x18, %ax \n"
+ " mov %ax, %ds \n"
+ " mov %ax, %es \n"
+ " mov %ax, %fs \n"
+ " mov %ax, %gs \n"
+ " mov %ax, %ss \n"
+ /* restore proper gdt and idt */
+ " lgdt %cs:gdtarg \n"
+ " lidt idtarg \n"
+ ".globl vga_exit \n"
+ "vga_exit: \n"
+ " mov __stack, %esp \n"
+ " popal \n");
+}
+
+__asm__(".text\n" "real_mode_switch_end:\n");
+extern char real_mode_switch_end[];
+
+/* call vga bios int 10 function 0x4f14 to enable main console
+ epia-m does not always autosence the main console so forcing it on is good !! */
+void vga_enable_console()
+{
+ if ((acpi_sleep_type == 0) && (PAYLOAD_IS_SEABIOS == 1))
+ return;
+ __asm__ __volatile__(
+ /* paranoia -- does ecx get saved? not sure. This is
+ * the easiest safe thing to do. */
+ " pushal \n"
+ /* save the stack */
+ " mov %esp, __stack \n"
+ /* load 'our' gdt */
+ " lgdt %cs:__mygdtaddr \n"
+ /* This configures CS properly for real mode. */
+ " ljmp $0x28, $__vga_ec_16bit\n"
+ "__vga_ec_16bit: \n"
+ " .code16 \n"
+ /* 16 bit code from here on... */
+ /* Load the segment registers w/ properly configured segment
+ * descriptors. They will retain these configurations (limits,
+ * writability, etc.) once protected mode is turned off. */
+ " mov $0x30, %ax \n"
+ " mov %ax, %ds \n"
+ " mov %ax, %es \n"
+ " mov %ax, %fs \n"
+ " mov %ax, %gs \n"
+ " mov %ax, %ss \n"
+ /* Turn off protection (bit 0 in CR0) */
+ " movl %cr0, %eax \n"
+ " andl $0xFFFFFFFE, %eax\n"
+ " movl %eax, %cr0 \n"
+ /* Now really going into real mode */
+ " ljmp $0, $__vga_ec_real \n"
+ "__vga_ec_real: \n"
+ /* put the stack at the end of page zero.
+ * that way we can easily share it between real and protected,
+ * since the 16-bit ESP at segment 0 will work for any case.
+ /* Setup a stack */
+ " mov $0x0, %ax \n"
+ " mov %ax, %ss \n"
+ " movl $0x1000, %eax \n"
+ " movl %eax, %esp \n"
+ /* debugging for RGM */
+ " mov $0x11, %al \n"
+ " outb %al, $0x80 \n"
+ /* Load our 16 it idt */
+ " xor %ax, %ax \n"
+ " mov %ax, %ds \n"
+ " lidt __myidt \n"
+ /* Dump zeros in the other segregs */
+ " mov %ax, %ds \n"
+ " mov %ax, %es \n"
+ " mov %ax, %fs \n"
+ " mov %ax, %gs \n"
+ /* ask bios to enable main console */
+ /* set up for int 10 call - values found from X server
+ * bios call routines */
+ " movw $0x4f14,%ax \n"
+ " movw $0x8003,%bx \n"
+ " movw $1, %cx \n"
+ " movw $0, %dx \n"
+ " movw $0, %di \n"
+ " int $0x10 \n"
+ " movb $0x55, %al \n"
+ " outb %al, $0x80 \n"
+ /* if we got here, just about done.
+ * Need to get back to protected mode */
+ " movl %cr0, %eax \n" " orl $0x0000001, %eax\n" /* PE = 1 */
+ " movl %eax, %cr0 \n"
+ /* Now that we are in protected mode jump to a 32 bit code segment. */
+ " data32 ljmp $0x10, $vga_ec_restart\n"
+ "vga_ec_restart:\n"
+ " .code32\n"
+ " movw $0x18, %ax \n"
+ " mov %ax, %ds \n"
+ " mov %ax, %es \n"
+ " mov %ax, %fs \n"
+ " mov %ax, %gs \n"
+ " mov %ax, %ss \n"
+ /* restore proper gdt and idt */
+ " lgdt %cs:gdtarg \n"
+ " lidt idtarg \n"
+ " .globl vga__ec_exit \n"
+ "vga_ec_exit:\n"
+ " mov __stack, %esp \n"
+ " popal\n");
+}
+
+void do_vgabios(void)
+{
+ device_t dev;
+ unsigned long busdevfn;
+ unsigned int rom = 0;
+ unsigned char *buf;
+ unsigned int size = 64 * 1024;
+ int i;
+ u16 tmp;
+ u8 tmp8;
+
+ printk_emerg("file '%s', line %d\n\n", __FILE__, __LINE__);
+
+ /* clear vga bios data area */
+ for (i = 0x400; i < 0x500; i++) {
+ *(unsigned char *) i = 0;
+ }
+
+ dev = dev_find_class(PCI_CLASS_DISPLAY_VGA << 8, 0);
+
+ if (!dev) {
+ printk_debug("NO VGA FOUND\n");
+ return;
+ }
+ printk_debug("found VGA: vid=%x, did=%x\n", dev->vendor,
+ dev->device);
+
+ /* declare rom address here - keep any config data out of the way
+ * of core LXB stuff */
+
+ rom = 0xffffffff - FULL_ROM_SIZE + 1;
+ pci_write_config32(dev, PCI_ROM_ADDRESS, rom | 1);
+ printk_debug("rom base: %x\n", rom);
+ buf = (unsigned char *) rom;
+ printk_emerg("file '%s', line %d\n\n", __FILE__, __LINE__);
+
+ if ((buf[0] == 0x55) && (buf[1] == 0xaa)) {
+ memcpy((void *) 0xc0000, buf, size);
+
+
+ printk_emerg("file '%s', line %d\n\n", __FILE__, __LINE__);
+
+ write_protect_vgabios(); // in northbridge
+
+ // check signature again
+ buf = (unsigned char *) 0xc0000;
+ if (buf[0] == 0x55 && buf[1] == 0xAA) {
+ busdevfn =
+ (dev->bus->secondary << 8) | dev->path.pci.
+ devfn;
+ printk_debug("bus/devfn = %#x\n", busdevfn);
+ real_mode_switch_call_vga(busdevfn);
+ } else
+ printk_debug
+ ("Failed to copy VGA BIOS to 0xc0000\n");
+ } else
+ printk_debug("BAD SIGNATURE 0x%x 0x%x\n", buf[0], buf[1]);
+
+ printk_emerg("file '%s', line %d\n\n", __FILE__, __LINE__);
+
+ pci_write_config32(dev, PCI_ROM_ADDRESS, 0);
+}
+
+
+// we had hoped to avoid this.
+// this is a stub IDT only. It's main purpose is to ignore calls
+// to the BIOS.
+// no longer. Dammit. We have to respond to these.
+struct realidt {
+ unsigned short offset, cs;
+};
+
+// from a handy writeup that andrey found.
+
+// handler.
+// There are some assumptions we can make here.
+// First, the Top Of Stack (TOS) is located on the top of page zero.
+// we can share this stack between real and protected mode.
+// that simplifies a lot of things ...
+// we'll just push all the registers on the stack as longwords,
+// and pop to protected mode.
+// second, since this only ever runs as part of coreboot,
+// we know all the segment register values -- so we don't save any.
+// keep the handler that calls things small. It can do a call to
+// more complex code in coreboot itself. This helps a lot as we don't
+// have to do address fixup in this little stub, and calls are absolute
+// so the handler is relocatable.
+void handler(void)
+{
+ __asm__ __volatile__(" .code16 \n"
+ "idthandle: \n"
+ " pushal \n"
+ " movb $0, %al \n"
+ " ljmp $0, $callbiosint16\n"
+ "end_idthandle: \n"
+ " .code32 \n");
+}
+
+void debughandler(void)
+{
+ __asm__ __volatile__(" .code16 \n"
+ "debughandle: \n"
+ " pushw %cx \n"
+ " movw $250, %cx \n"
+ "dbh1: \n"
+ " loop dbh1 \n"
+ " popw %cx \n"
+ " iret \n"
+ "end_debughandle: \n"
+ ".code32 \n");
+}
+
+// Calling conventions. The first C function is called with this stuff
+// on the stack. They look like value parameters, but note that if you
+// modify them they will go back to the INTx function modified.
+// the C function will call the biosint function with these as
+// REFERENCE parameters. In this way, we can easily get
+// returns back to the INTx caller (i.e. vgabios)
+void callbiosint(void)
+{
+ __asm__ __volatile__(" .code16 \n"
+ "callbiosint16: \n"
+ " push %ds \n"
+ " push %es \n"
+ " push %fs \n" " push %gs \n"
+ // clean up the int #. To save space we put it in the lower
+ // byte. But the top 24 bits are junk.
+ " andl $0xff, %eax\n"
+ // this push does two things:
+ // - put the INT # on the stack as a parameter
+ // - provides us with a temp for the %cr0 mods.
+ " pushl %eax \n" " movl %cr0, %eax\n" " orl $0x00000001, %eax\n" /* PE = 1 */
+ " movl %eax, %cr0\n"
+ /* Now that we are in protected mode jump to a 32 bit code segment. */
+ " data32 ljmp $0x10, $biosprotect\n"
+ "biosprotect: \n"
+ " .code32 \n"
+ " movw $0x18, %ax \n"
+ " mov %ax, %ds \n"
+ " mov %ax, %es \n"
+ " mov %ax, %fs \n"
+ " mov %ax, %gs \n"
+ " mov %ax, %ss \n"
+ " lidt idtarg \n"
+ " call biosint \n"
+ // back to real mode ...
+ " ljmp $0x28, $__rms_16bit2\n"
+ "__rms_16bit2: \n"
+ " .code16 \n"
+ /* 16 bit code from here on... */
+ /* Load the segment registers w/ properly configured segment
+ * descriptors. They will retain these configurations (limits,
+ * writability, etc.) once protected mode is turned off. */
+ " mov $0x30, %ax \n"
+ " mov %ax, %ds \n"
+ " mov %ax, %es \n"
+ " mov %ax, %fs \n"
+ " mov %ax, %gs \n"
+ " mov %ax, %ss \n"
+ /* Turn off protection (bit 0 in CR0) */
+ " movl %cr0, %eax \n"
+ " andl $0xFFFFFFFE, %eax \n"
+ " movl %eax, %cr0 \n"
+ /* Now really going into real mode */
+ " ljmp $0, $__rms_real2 \n"
+ "__rms_real2: \n"
+ /* Setup a stack
+ * FixME: where is esp? */
+ " mov $0x0, %ax \n"
+ " mov %ax, %ss \n"
+ /* ebugging for RGM */
+ " mov $0x11, %al \n"
+ " outb %al, $0x80 \n"
+ /* Load our 16 it idt */
+ " xor %ax, %ax \n"
+ " mov %ax, %ds \n"
+ " lidt __myidt \n"
+ /* Dump zeros in the other segregs */
+ " mov %ax, %es \n"
+ " mov %ax, %fs \n"
+ " mov %ax, %gs \n"
+ " mov $0x40, %ax \n"
+ " mov %ax, %ds \n"
+ /* pop the INT # that you pushed earlier */
+ " popl %eax \n"
+ " pop %gs \n"
+ " pop %fs \n"
+ " pop %es \n"
+ " pop %ds \n"
+ " popal \n"
+ " iret \n"
+ " .code32 \n");
+}
+
+enum {
+ PCIBIOS = 0x1a,
+ MEMSIZE = 0x12
+};
+
+int pcibios(unsigned long *pedi, unsigned long *pesi, unsigned long *pebp,
+ unsigned long *pesp, unsigned long *pebx, unsigned long *pedx,
+ unsigned long *pecx, unsigned long *peax,
+ unsigned long *pflags);
+
+int handleint21(unsigned long *pedi, unsigned long *pesi,
+ unsigned long *pebp, unsigned long *pesp,
+ unsigned long *pebx, unsigned long *pedx,
+ unsigned long *pecx, unsigned long *peax,
+ unsigned long *pflags);
+
+extern void vga_exit(void);
+
+int biosint(unsigned long intnumber,
+ unsigned long gsfs, unsigned long dses,
+ unsigned long edi, unsigned long esi,
+ unsigned long ebp, unsigned long esp,
+ unsigned long ebx, unsigned long edx,
+ unsigned long ecx, unsigned long eax,
+ unsigned long cs_ip, unsigned short stackflags)
+{
+ unsigned long ip;
+ unsigned long cs;
+ unsigned long flags;
+ int ret = -1;
+
+ ip = cs_ip & 0xffff;
+ cs = cs_ip >> 16;
+ flags = stackflags;
+
+ printk_debug("biosint: INT# 0x%lx\n", intnumber);
+ printk_debug("biosint: eax 0x%lx ebx 0x%lx ecx 0x%lx edx 0x%lx\n",
+ eax, ebx, ecx, edx);
+ printk_debug("biosint: ebp 0x%lx esp 0x%lx edi 0x%lx esi 0x%lx\n",
+ ebp, esp, edi, esi);
+ printk_debug("biosint: ip 0x%x cs 0x%x flags 0x%x\n",
+ ip, cs, flags);
+
+ // cases in a good compiler are just as good as your own tables.
+ switch (intnumber) {
+ case 0...15:
+ // These are not BIOS service, but the CPU-generated exceptions
+ printk_info("biosint: Oops, exception %u\n", intnumber);
+ if (esp < 0x1000) {
+ printk_debug("Stack contents: ");
+ while (esp < 0x1000) {
+ printk_debug("0x%04x ",
+ *(unsigned short *) esp);
+ esp += 2;
+ }
+ printk_debug("\n");
+ }
+ printk_debug("biosint: Bailing out\n");
+ // "longjmp"
+ if ((acpi_sleep_type == 3) || (PAYLOAD_IS_SEABIOS == 0)) // add this to keep same with kevin's seabios patch in 2008-9-8
+ vga_exit();
+ break;
+
+ case PCIBIOS:
+ ret = pcibios(&edi, &esi, &ebp, &esp,
+ &ebx, &edx, &ecx, &eax, &flags);
+ break;
+ case MEMSIZE:
+ // who cares.
+ eax = 64 * 1024;
+ ret = 0;
+ break;
+ case 0x15:
+ ret = handleint21(&edi, &esi, &ebp, &esp,
+ &ebx, &edx, &ecx, &eax, &flags);
+ break;
+ default:
+ printk_info("BIOSINT: Unsupport int #0x%x\n", intnumber);
+ break;
+ }
+ if (ret)
+ flags |= 1; // carry flags
+ else
+ flags &= ~1;
+ stackflags = flags;
+ return ret;
+}
+
+
+void setup_realmode_idt(void)
+{
+ extern unsigned char idthandle, end_idthandle;
+ extern unsigned char debughandle, end_debughandle;
+
+ int i;
+ struct realidt *idts = (struct realidt *) 0;
+ int codesize = &end_idthandle - &idthandle;
+ unsigned char *intbyte, *codeptr;
+
+ // for each int, we create a customized little handler
+ // that just pushes %ax, puts the int # in %al,
+ // then calls the common interrupt handler.
+ // this necessitated because intel didn't know much about
+ // architecture when they did the 8086 (it shows)
+ // (hmm do they know anymore even now :-)
+ // obviously you can see I don't really care about memory
+ // efficiency. If I did I would probe back through the stack
+ // and get it that way. But that's really disgusting.
+ for (i = 0; i < 256; i++) {
+ idts[i].cs = 0;
+ codeptr = (char *) 4096 + i * codesize;
+ idts[i].offset = (unsigned) codeptr;
+ memcpy(codeptr, &idthandle, codesize);
+ intbyte = codeptr + 3;
+ *intbyte = i;
+ }
+
+ // fixed entry points
+
+ // VGA BIOSes tend to hardcode f000:f065 as the previous handler of
+ // int10.
+ // calling convention here is the same as INTs, we can reuse
+ // the int entry code.
+ codeptr = (char *) 0xff065;
+ memcpy(codeptr, &idthandle, codesize);
+ intbyte = codeptr + 3;
+ *intbyte = 0x42; /* int42 is the relocated int10 */
+/*
+ Fixed entry points
+ VBIOS will call f000:f859 instead of sending int15.
+ calling convertion here is the same as INTs, we can reuse the int entry code.
+*/
+ codeptr = (char *) 0xff859;
+ memcpy(codeptr, &idthandle, codesize);
+ intbyte = codeptr + 3;
+ *intbyte = 0x15;
+
+ /* debug handler - useful to set a programmable delay between instructions if the
+ TF bit is set upon call to real mode */
+ idts[1].cs = 0;
+ idts[1].offset = 16384;
+ memcpy(16384, &debughandle, &end_debughandle - &debughandle);
+
+
+}
+
+
+
+enum {
+ CHECK = 0xb001,
+ FINDDEV = 0xb102,
+ READCONFBYTE = 0xb108,
+ READCONFWORD = 0xb109,
+ READCONFDWORD = 0xb10a,
+ WRITECONFBYTE = 0xb10b,
+ WRITECONFWORD = 0xb10c,
+ WRITECONFDWORD = 0xb10d
+};
+
+// errors go in AH. Just set these up so that word assigns
+// will work. KISS.
+enum {
+ PCIBIOS_NODEV = 0x8600,
+ PCIBIOS_BADREG = 0x8700
+};
+
+int
+pcibios(unsigned long *pedi, unsigned long *pesi, unsigned long *pebp,
+ unsigned long *pesp, unsigned long *pebx, unsigned long *pedx,
+ unsigned long *pecx, unsigned long *peax, unsigned long *pflags)
+{
+ unsigned long edi = *pedi;
+ unsigned long esi = *pesi;
+ unsigned long ebp = *pebp;
+ unsigned long esp = *pesp;
+ unsigned long ebx = *pebx;
+ unsigned long edx = *pedx;
+ unsigned long ecx = *pecx;
+ unsigned long eax = *peax;
+ unsigned long flags = *pflags;
+ unsigned short func = (unsigned short) eax;
+ int retval = 0;
+ unsigned short devid, vendorid, devfn;
+ short devindex; /* Use short to get rid of garbage in upper half of 32-bit register */
+ unsigned char bus;
+ device_t dev;
+
+ switch (func) {
+ case CHECK:
+ *pedx = 0x4350;
+ *pecx = 0x2049;
+ retval = 0;
+ break;
+ case FINDDEV:
+ {
+ devid = *pecx;
+ vendorid = *pedx;
+ devindex = *pesi;
+ dev = 0;
+ while ((dev =
+ dev_find_device(vendorid, devid, dev))) {
+ if (devindex <= 0)
+ break;
+ devindex--;
+ }
+ if (dev) {
+ unsigned short busdevfn;
+ *peax = 0;
+ // busnum is an unsigned char;
+ // devfn is an int, so we mask it off.
+ busdevfn = (dev->bus->secondary << 8)
+ | (dev->path.pci.devfn & 0xff);
+ printk_debug("0x%x: return 0x%x\n", func,
+ busdevfn);
+ *pebx = busdevfn;
+ retval = 0;
+ } else {
+ *peax = PCIBIOS_NODEV;
+ retval = -1;
+ }
+ }
+ break;
+ case READCONFDWORD:
+ case READCONFWORD:
+ case READCONFBYTE:
+ case WRITECONFDWORD:
+ case WRITECONFWORD:
+ case WRITECONFBYTE:
+ {
+ unsigned long dword;
+ unsigned short word;
+ unsigned char byte;
+ unsigned char reg;
+
+ devfn = *pebx & 0xff;
+ bus = *pebx >> 8;
+ reg = *pedi;
+ dev = dev_find_slot(bus, devfn);
+ if (!dev) {
+ printk_debug
+ ("0x%x: BAD DEVICE bus %d devfn 0x%x\n",
+ func, bus, devfn);
+ // idiots. the pcibios guys assumed you'd never pass a bad bus/devfn!
+ *peax = PCIBIOS_BADREG;
+ retval = -1;
+ }
+ switch (func) {
+ case READCONFBYTE:
+ byte = pci_read_config8(dev, reg);
+ *pecx = byte;
+ break;
+ case READCONFWORD:
+ word = pci_read_config16(dev, reg);
+ *pecx = word;
+ break;
+ case READCONFDWORD:
+ dword = pci_read_config32(dev, reg);
+ *pecx = dword;
+ break;
+ case WRITECONFBYTE:
+ byte = *pecx;
+ pci_write_config8(dev, reg, byte);
+ break;
+ case WRITECONFWORD:
+ word = *pecx;
+ pci_write_config16(dev, reg, word);
+ break;
+ case WRITECONFDWORD:
+ dword = *pecx;
+ pci_write_config32(dev, reg, dword);
+ break;
+ }
+
+ if (retval)
+ retval = PCIBIOS_BADREG;
+ printk_debug
+ ("0x%x: bus %d devfn 0x%x reg 0x%x val 0x%lx\n",
+ func, bus, devfn, reg, *pecx);
+ *peax = 0;
+ retval = 0;
+ }
+ break;
+ default:
+ printk_err("UNSUPPORTED PCIBIOS FUNCTION 0x%x\n", func);
+ break;
+ }
+
+ return retval;
+}
+
+
+/* return value of int0x15(int21)
+AH AL Completion status
+?? 5Fh Function call supported
+?? !=5Fh Function not supported
+00 5Fh Function call successful
+01 5Fh Function call failed
+*/
+int handleint21(unsigned long *edi, unsigned long *esi, unsigned long *ebp,
+ unsigned long *esp, unsigned long *ebx, unsigned long *edx,
+ unsigned long *ecx, unsigned long *eax,
+ unsigned long *flags)
+{
+ int res = -1;
+ switch (*eax & 0xffff) {
+ case 0x5f19:
+ *eax = 0x5f;
+ *ecx = 0x3;
+ res = 0;
+ break;
+ case 0x5f18:
+ {
+ /*
+ BL
+ Bit[7:4]
+ Memory Data Rate
+ 0000: 66MHz
+ 0001: 100MHz
+ 0010: 133MHz
+ 0011: 200MHz ( DDR200 )
+ 0100: 266MHz ( DDR266 )
+ 0101: 333MHz ( DDR333 )
+ 0110: 400MHz ( DDR400 )
+ 0111: 533MHz ( DDR I/II 533
+ 1000: 667MHz ( DDR I/II 667)
+ Bit[3:0]
+ N: Frame Buffer Size 2^N MB
+ */
+ u8 i;
+ device_t dev;
+ dev = dev_find_slot(0, PCI_DEVFN(0, 3));
+ i = pci_read_config8(dev, 0xa1);
+ i = (i & 0x70);
+ i = i >> 4;
+ if (i == 0) {
+ *eax = 0x00; //not support 5f18
+ break;
+ }
+ i = i + 2;
+ *ebx = (u32) i;
+ i = pci_read_config8(dev, 0x90);
+ i = (i & 0x07);
+ i = i + 3;
+ i = i << 4;
+ *ebx = (*ebx) + ((u32) i);
+ *eax = 0x5f;
+ res = 0;
+ break;
+ }
+ case 0x5f00:
+ *eax = 0x005f;
+ res = 0;
+ break;
+ case 0x5f01:
+ *eax = 0x5f;
+ *ecx = (*ecx & 0xffffff00) | 2; // panel type = 2 = 1024 * 768
+ res = 0;
+ break;
+ case 0x5f02:
+ *eax = 0x5f;
+ *ebx = (*ebx & 0xffff0000) | 2;
+ *ecx = (*ecx & 0xffff0000) | 0x401; // PAL + crt only
+ *edx = (*edx & 0xffff0000) | 0; // TV Layout - default
+ res = 0;
+ break;
+ case 0x5f0f:
+ *eax = 0x005f;
+ res = 0;
+ break;
+ default:
+ *eax = 0;
+ break;
+ }
+ return res;
+}
diff --git a/src/northbridge/via/vx800/vgachip.h b/src/northbridge/via/vx800/vgachip.h
new file mode 100644
index 0000000000..86e948bd91
--- /dev/null
+++ b/src/northbridge/via/vx800/vgachip.h
@@ -0,0 +1,34 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007 Corey Osgood <corey.osgood@gmail.com>
+ *
+ * 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
+ */
+
+#ifndef _PC80_VGABIOS
+#define _PC80_VGABIOS
+
+extern struct chip_control pc80_vgabios_control;
+
+struct pc80_vgabios_config {
+ int nothing;
+};
+
+void vga_enable_console(void);
+void do_vgabios(void);
+void setup_realmode_idt(void);
+void write_protect_vgabios(void);
+
+#endif /* _PC80_VGABIOS */
diff --git a/src/northbridge/via/vx800/vx800.h b/src/northbridge/via/vx800/vx800.h
new file mode 100644
index 0000000000..3955f1fc4c
--- /dev/null
+++ b/src/northbridge/via/vx800/vx800.h
@@ -0,0 +1,125 @@
+/*
+ * 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
+ */
+
+#ifndef VX800_H
+#define VX800_H 1
+
+
+#ifndef __ROMCC__
+static void vx800_noop(){}
+#endif
+#define REV_B0 0x10
+#define REV_B1 0x11
+#define REV_B2 0x12
+#define REV_B3 0x13
+#define REV_B4 0x14
+#define REV_B2 0xB4
+#define REV_B0 0x00
+#define REV_B2 0x01
+
+/* VGA stuff */
+#define SR_INDEX 0x3c4
+#define SR_DATA 0x3c5
+#define CRTM_INDEX 0x3b4
+#define CRTM_DATA 0x3b5
+#define CRTC_INDEX 0x3d4
+#define CRTC_DATA 0x3d5
+
+/* Memory Controller Registers */
+#define RANK0_END 0x40
+#define RANK1_END 0x41
+#define RANK2_END 0x42
+#define RANK3_END 0x43
+#define RANK0_START 0x48
+#define RANK1_START 0x49
+#define RANK2_START 0x4a
+#define RANK3_START 0x4b
+#define DDR_PAGE_CTL 0x69
+#define DRAM_REFRESH_COUNTER 0x6a
+#define DRAM_MISC_CTL 0x6b
+#define CH_A_DQS_OUTPUT_DELAY 0x70
+#define CH_A_MD_OUTPUT_DELAY 0x71
+
+/* RAM Init Commands */
+#define RAM_COMMAND_NORMAL 0x0
+#define RAM_COMMAND_NOP 0x1
+#define RAM_COMMAND_PRECHARGE 0x2
+#define RAM_COMMAND_MRS 0x3
+#define RAM_COMMAND_CBR 0x4
+
+
+
+
+/* IDE specific bits */
+#define IDE_MODE_REG 0x09
+#define IDE0_NATIVE_MODE (1 << 0)
+#define IDE1_NATIVE_MODE (1 << 2)
+
+/* These are default addresses according to Via */
+#define IDE0_DATA_ADDR 0x1f0
+#define IDE0_CONTROL_ADDR 0x3f4
+#define IDE1_DATA_ADDR 0x170
+#define IDE1_CONTROL_ADDR 0x370
+
+
+/* By Award default, Via default is 0xCC0 */
+#define BUS_MASTER_ADDR 0xfe00
+
+#define CHANNEL_ENABLE_REG 0x40
+#define ENABLE_IDE0 (1 << 0)
+#define ENABLE_IDE1 (1 << 1)
+
+
+
+#define VX800_ACPI_IO_BASE 0x0400
+
+
+#define NB_APIC_REG 0,0,5,
+#define NB_PXPTRF_REG NB_APIC_REG
+#define NB_MSGC_REG NB_APIC_REG
+#define NB_HOST_REG 0,0,2,
+#define NB_P6IF_REG NB_HOST_REG
+
+#define NB_DRAMC_REG 0,0,3,
+#define NB_PMU_REG 0,0,4,
+#define NB_VLINK_REG 0,0,7,
+#define NB_PEG_BRIDGE_REG 0,2, 0,
+#define NB_D3F0_REG 0,3, 0,
+#define NB_D3F1_REG 0,3, 1,
+
+
+#define SB_LPC_REG 0,0x11,0,
+#define SB_VLINK_REG 0,0x11,7,
+#define SB_SATA_REG 0,0xf, 0,
+#define SB_IDEC_REG 0,0xf, 0,
+#define SB_P2PB_REG 0,0x13, 0,
+#define SB_USB0_REG 0,0x10, 0,
+#define SB_USB1_REG 0,0x10, 1,
+#define SB_USB2_REG 0,0x10, 2,
+#define SB_EHCI_REG 0,0x10, 4,
+
+
+#define VX800SB_APIC_ID 0x4
+#define VX800SB_APIC_BASE 0xfec00000ULL
+#define VX800SB_APIC_DATA_OFFSET 0x10
+#define VX800SB_APIC_ENTRY_NUMBER 0x40
+
+#define VX800_D0F5_MMCONFIG_MBAR 0x61
+
+#endif
diff --git a/src/northbridge/via/vx800/vx800_early_serial.c b/src/northbridge/via/vx800/vx800_early_serial.c
new file mode 100644
index 0000000000..dfc5c3e235
--- /dev/null
+++ b/src/northbridge/via/vx800/vx800_early_serial.c
@@ -0,0 +1,110 @@
+/*
+ * 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
+*/
+
+/*
+ * Enable the serial devices on the VIA
+ */
+#include <arch/romcc_io.h>
+
+/* The base address is 0x15c, 0x2e, depending on config bytes */
+
+#define SIO_BASE 0x3f0
+#define SIO_DATA SIO_BASE+1
+
+static void vx800_writesuper(uint8_t reg, uint8_t val)
+{
+ outb(reg, SIO_BASE);
+ outb(val, SIO_DATA);
+}
+
+static void vx800_writepnpaddr(uint8_t val)
+{
+ outb(val, 0x2e);
+ outb(val, 0xeb);
+}
+
+static void vx800_writepnpdata(uint8_t val)
+{
+ outb(val, 0x2f);
+ outb(val, 0xeb);
+}
+
+static void vx800_writesiobyte(uint16_t reg, uint8_t val)
+{
+ outb(val, reg);
+}
+
+static void vx800_writesioword(uint16_t reg, uint16_t val)
+{
+ outw(val, reg);
+}
+
+
+/* regs we use: 85, and the southbridge devfn is defined by the
+ mainboard
+ */
+
+static void enable_vx800_serial(void)
+{
+ outb(6, 0x80);
+ outb(0x03, 0x22);
+
+
+ //pci_write_config8(PCI_DEV(0,17,0),0xb4,0x7e);
+ //pci_write_config8(PCI_DEV(0,17,0),0xb0,0x10);
+
+ // turn on pnp
+ vx800_writepnpaddr(0x87);
+ vx800_writepnpaddr(0x87);
+ // now go ahead and set up com1.
+ // set address
+ vx800_writepnpaddr(0x7);
+ vx800_writepnpdata(0x2);
+ // enable serial out
+ vx800_writepnpaddr(0x30);
+ vx800_writepnpdata(0x1);
+ // serial port 1 base address (FEh)
+ vx800_writepnpaddr(0x60);
+ vx800_writepnpdata(0xfe);
+ // serial port 1 IRQ (04h)
+ vx800_writepnpaddr(0x70);
+ vx800_writepnpdata(0x4);
+ // serial port 1 control
+ vx800_writepnpaddr(0xf0);
+ vx800_writepnpdata(0x2);
+ // turn of pnp
+ vx800_writepnpaddr(0xaa);
+
+ // set up reg to set baud rate.
+ vx800_writesiobyte(0x3fb, 0x80);
+ // Set 115 kb
+ vx800_writesioword(0x3f8, 1);
+ // Set 9.6 kb
+ // WRITESIOWORD(0x3f8, 12)
+ // now set no parity, one stop, 8 bits
+ vx800_writesiobyte(0x3fb, 3);
+ // now turn on RTS, DRT
+ vx800_writesiobyte(0x3fc, 3);
+ // Enable interrupts
+ vx800_writesiobyte(0x3f9, 0xf);
+ // should be done. Dump a char for fun.
+ vx800_writesiobyte(0x3f8, 48);
+ outb(7, 0x80);
+}
+
diff --git a/src/northbridge/via/vx800/vx800_early_smbus.c b/src/northbridge/via/vx800/vx800_early_smbus.c
new file mode 100644
index 0000000000..03deedc8aa
--- /dev/null
+++ b/src/northbridge/via/vx800/vx800_early_smbus.c
@@ -0,0 +1,321 @@
+/*
+ * 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
+ */
+
+ #include <device/pci_ids.h>
+ #include "vx800.h"
+#define SMBUS_IO_BASE 0x0500 //from award bios
+#define PMIO_BASE VX800_ACPI_IO_BASE //might as well set this while we're here
+
+#define SMBHSTSTAT SMBUS_IO_BASE + 0x0
+#define SMBSLVSTAT SMBUS_IO_BASE + 0x1
+#define SMBHSTCTL SMBUS_IO_BASE + 0x2
+#define SMBHSTCMD SMBUS_IO_BASE + 0x3
+#define SMBXMITADD SMBUS_IO_BASE + 0x4
+#define SMBHSTDAT0 SMBUS_IO_BASE + 0x5
+#define SMBHSTDAT1 SMBUS_IO_BASE + 0x6
+/* Rest of these aren't currently used... */
+#define SMBBLKDAT SMBUS_IO_BASE + 0x7
+#define SMBSLVCTL SMBUS_IO_BASE + 0x8
+#define SMBTRNSADD SMBUS_IO_BASE + 0x9
+#define SMBSLVDATA SMBUS_IO_BASE + 0xa
+#define SMLINK_PIN_CTL SMBUS_IO_BASE + 0xe
+#define SMBUS_PIN_CTL SMBUS_IO_BASE + 0xf
+
+/* Define register settings */
+#define HOST_RESET 0xff
+#define DIMM_BASE 0xa0 // 1010000 is base for DIMM in SMBus
+#define READ_CMD 0x01 // 1 in the 0 bit of SMBHSTADD states to READ
+
+#define SMBUS_TIMEOUT (100*1000*10)
+
+#define I2C_TRANS_CMD 0x40
+#define CLOCK_SLAVE_ADDRESS 0x69
+
+#define SMBUS_DELAY() outb(0x80, 0x80)
+
+/* Debugging macros. Only necessary if something isn't working right */
+
+#define DEBUG_SMBUS 1
+
+#ifdef DEBUG_SMBUS
+#define PRINT_DEBUG(x) print_debug(x)
+#define PRINT_DEBUG_HEX16(x) print_debug_hex16(x)
+#else
+#define PRINT_DEBUG(x)
+#define PRINT_DEBUG_HEX16(x)
+#endif
+
+/* Internal functions */
+static void smbus_print_error(unsigned char host_status_register, int loops)
+{
+// print_err("some i2c error\r\n");
+ /* Check if there actually was an error */
+ if ( host_status_register == 0x00 || host_status_register == 0x40 ||
+ host_status_register == 0x42) return;
+ print_err("smbus_error: ");
+ print_err_hex8(host_status_register);
+ print_err("\r\n");
+ if (loops >= SMBUS_TIMEOUT) {
+ print_err("SMBus Timout\r\n");
+ }
+ if (host_status_register & (1 << 4)) {
+ print_err("Interrup/SMI# was Failed Bus Transaction\r\n");
+ }
+ if (host_status_register & (1 << 3)) {
+ print_err("Bus Error\r\n");
+ }
+ if (host_status_register & (1 << 2)) {
+ print_err("Device Error\r\n");
+ }
+ if (host_status_register & (1 << 1)) {
+ /* This isn't a real error... */
+ print_debug("Interrupt/SMI# was Successful Completion\r\n");
+ }
+ if (host_status_register & (1 << 0)) {
+ print_err("Host Busy\r\n");
+ }
+}
+
+static void smbus_wait_until_ready(void)
+{
+ int loops;
+
+ loops = 0;
+ /* Yes, this is a mess, but it's the easiest way to do it */
+ while(((inb(SMBHSTSTAT) & 1) == 1) && (loops <= SMBUS_TIMEOUT)) {
+ SMBUS_DELAY();
+ ++loops;
+ }
+ smbus_print_error(inb(SMBHSTSTAT), loops);
+}
+
+static void smbus_reset(void)
+{
+ outb(HOST_RESET, SMBHSTSTAT);
+}
+
+/* Public functions */
+static unsigned int set_ics_data(unsigned char dev, int data, char len)
+{
+ int i;
+ smbus_reset();
+ /* clear host data port */
+ outb(0x00, SMBHSTDAT0);
+ SMBUS_DELAY();
+ smbus_wait_until_ready();
+
+ /* read to reset block transfer counter */
+ inb(SMBHSTCTL);
+
+ /* fill blocktransfer array */
+ if (dev=0xd2) {
+ //char d2_data[] = {0x0d,0x00,0x3f,0xcd,0x7f,0xbf,0x1a,0x2a,0x01,0x0f,0x0b,0x00,0x8d,0x9b};
+ outb(0x0d,SMBBLKDAT);
+ outb(0x00,SMBBLKDAT);
+ outb(0x3f,SMBBLKDAT);
+ outb(0xcd,SMBBLKDAT);
+ outb(0x7f,SMBBLKDAT);
+ outb(0xbf,SMBBLKDAT);
+ outb(0x1a,SMBBLKDAT);
+ outb(0x2a,SMBBLKDAT);
+ outb(0x01,SMBBLKDAT);
+ outb(0x0f,SMBBLKDAT);
+ outb(0x0b,SMBBLKDAT);
+ outb(0x80,SMBBLKDAT);
+ outb(0x8d,SMBBLKDAT);
+ outb(0x9b,SMBBLKDAT);
+ } else {
+ //char d4_data[] = {0x08,0xff,0x3f,0x00,0x00,0xff,0xff,0xff,0xff};
+ outb(0x08,SMBBLKDAT);
+ outb(0xff,SMBBLKDAT);
+ outb(0x3f,SMBBLKDAT);
+ outb(0x00,SMBBLKDAT);
+ outb(0x00,SMBBLKDAT);
+ outb(0xff,SMBBLKDAT);
+ outb(0xff,SMBBLKDAT);
+ outb(0xff,SMBBLKDAT);
+ outb(0xff,SMBBLKDAT);
+ }
+
+ //for (i=0; i < len; i++)
+ // outb(data[i],SMBBLKDAT);
+
+ outb(dev, SMBXMITADD);
+ outb(0, SMBHSTCMD);
+ outb(len, SMBHSTDAT0);
+ outb(0x74, SMBHSTCTL);
+
+ SMBUS_DELAY();
+
+ smbus_wait_until_ready();
+
+ smbus_reset();
+ return 0;
+}
+
+static unsigned int get_spd_data(unsigned int dimm, unsigned int offset)
+{
+ unsigned int val;
+
+ smbus_reset();
+ /* clear host data port */
+ outb(0x00, SMBHSTDAT0);
+ SMBUS_DELAY();
+ smbus_wait_until_ready();
+
+ /* Do some mathmatic magic */
+ dimm = (dimm << 1);
+ dimm &= 0x0E;
+ dimm |= 0xA0;
+
+ outb(dimm|0x1, SMBXMITADD);
+ outb(offset, SMBHSTCMD);
+ outb(0x48, SMBHSTCTL);
+
+ SMBUS_DELAY();
+
+ smbus_wait_until_ready();
+
+ val = inb(SMBHSTDAT0);
+ smbus_reset();
+ return val;
+}
+
+static void enable_smbus(void)
+{
+ device_t dev;
+
+ dev = pci_locate_device(PCI_ID(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX855_LPC), 0);
+
+ if (dev == PCI_DEV_INVALID) {
+ /* This won't display text if enable_smbus() is before serial init */
+ die("Power Managment Controller not found\r\n");
+ }
+
+ /* Set clock source */
+ pci_write_config8(dev, 0x94, 0x20);
+
+ /* Write SMBus IO base to 0xd0, and enable SMBus */
+ pci_write_config16(dev, 0xd0, SMBUS_IO_BASE | 1);
+
+ /* Set to Award value */
+ pci_write_config8(dev, 0xd2, 0x05);
+
+ /* Make it work for I/O ...*/
+ pci_write_config16(dev, 0x04, 0x0003);
+
+ /*
+ coreboot hangs at this two lines after os reboot(this even happen after I change os
+ reboot to cold reboot, this also interfere S3 wakeup)*/
+ /* Setup clock chips */
+ //set_ics_data(0xd2, 0, 14);
+ //set_ics_data(0xd4, 0, 9);
+
+ smbus_reset();
+ /* clear host data port */
+ outb(0x00, SMBHSTDAT0);
+ SMBUS_DELAY();
+ smbus_wait_until_ready();
+}
+
+/**
+ * A fixup for some systems that need time for the SMBus to "warm up". This is
+ * needed on some VT823x based systems, where the SMBus spurts out bad data for
+ * a short time after power on. This has been seen on the VIA Epia series and
+ * Jetway J7F2-series. It reads the ID byte from SMBus, looking for
+ * known-good data from a slot/address. Exits on either good data or a timeout.
+ *
+ * TODO: This should probably go into some global file, but one would need to
+ * be created just for it. If some other chip needs/wants it, we can
+ * worry about it then.
+ *
+ * @param ctrl The memory controller and SMBus addresses.
+ */
+void smbus_fixup(const struct mem_controller *ctrl)
+{
+ int i, ram_slots, current_slot = 0;
+ u8 result = 0;
+
+ ram_slots = ARRAY_SIZE(ctrl->channel0);
+ if (!ram_slots) {
+ print_err("smbus_fixup() thinks there are no RAM slots!\r\n");
+ return;
+ }
+
+ PRINT_DEBUG("Waiting for SMBus to warm up");
+
+ /*
+ * Bad SPD data should be either 0 or 0xff, but YMMV. So we look for
+ * the ID bytes of SDRAM, DDR, DDR2, and DDR3 (and anything in between).
+ * VT8237R has only been seen on DDR and DDR2 based systems, so far.
+ */
+ for (i = 0; (i < SMBUS_TIMEOUT && ((result < SPD_MEMORY_TYPE_SDRAM) ||
+ (result > SPD_MEMORY_TYPE_SDRAM_DDR3))); i++) {
+
+ if (current_slot > ram_slots)
+ current_slot = 0;
+
+ result = get_spd_data(ctrl->channel0[current_slot],
+ SPD_MEMORY_TYPE);
+ current_slot++;
+ PRINT_DEBUG(".");
+ }
+
+ if (i >= SMBUS_TIMEOUT)
+ print_err("SMBus timed out while warming up\r\n");
+ else
+ PRINT_DEBUG("Done\r\n");
+}
+
+/* Debugging Function */
+#ifdef DEBUG_SMBUS
+static void dump_spd_data(void)
+{
+ int dimm, offset, regs;
+ unsigned int val;
+
+ for(dimm = 0; dimm < 8; dimm++)
+ {
+ print_debug("SPD Data for DIMM ");
+ print_debug_hex8(dimm);
+ print_debug("\r\n");
+
+ val = get_spd_data(dimm, 0);
+ if(val == 0xff)
+ {
+ regs = 256;
+ } else if(val == 0x80) {
+ regs = 128;
+ } else {
+ print_debug("No DIMM present\r\n");
+ regs = 0;
+ }
+ for(offset = 0; offset < regs; offset++)
+ {
+ print_debug(" Offset ");
+ print_debug_hex8(offset);
+ print_debug(" = 0x");
+ print_debug_hex8(get_spd_data(dimm, offset));
+ print_debug("\r\n");
+ }
+ }
+}
+#else
+#define dump_spd_data()
+#endif
diff --git a/src/northbridge/via/vx800/vx800_ide.c b/src/northbridge/via/vx800/vx800_ide.c
new file mode 100644
index 0000000000..4f9f8f9c49
--- /dev/null
+++ b/src/northbridge/via/vx800/vx800_ide.c
@@ -0,0 +1,204 @@
+/*
+ * 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
+ */
+
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ops.h>
+#include <device/pci_ids.h>
+#include <console/console.h>
+#include "chip.h"
+#include <arch/io.h>
+#include "vx800.h"
+
+static const idedevicepcitable[16 * 12] = {
+//
+/*0x02, 0x00, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, 0x00, 0xA8, 0xA8, 0xF0, 0x00, 0x00, 0xB6,
+0x00, 0x00, 0x01, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x09, 0xC4, 0x06, 0x11, 0x09, 0xC4,
+0x00, 0xC2, 0xF9, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x02, 0x01, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+*/
+//
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, 0x00, 0x99, 0x20, 0xf0, 0x00, 0x00, 0x20,
+ 0x00, 0x00, 0x17, 0xF1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x09, 0xC4, 0x06, 0x11, 0x09, 0xC4,
+ 0x00, 0xc2, 0x09, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x01, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+//legacybios xp pci value
+/*0x02, 0x00, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x20, 0x00, 0x00, 0x00, 0xb6,
+0x00, 0x00, 0x16, 0xF1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x09, 0xC4, 0x06, 0x11, 0x09, 0xC4,
+0x00, 0x02, 0x09, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x02, 0x01, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+*/
+//rom legacybios on cn_8562b
+/*
+0x03, 0x00, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, 0x00, 0x99, 0x20, 0x60, 0x00, 0x00, 0x20,
+0x00, 0x00, 0x1E, 0xF1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x09, 0xC4, 0x06, 0x11, 0x09, 0xC4,
+0x00, 0x02, 0x09, 0x01, 0x18, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x02, 0x01, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+*/
+//from egacybios on c7_8562b
+/*0x03, 0x00, 0x00, 0x00, 0x00, 0x82, 0x00, 0x00, 0x00, 0x00, 0x5E, 0x20, 0x60, 0x00, 0x00, 0xB6,
+0x00, 0x00, 0x1E, 0xF1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x09, 0xC4, 0x06, 0x11, 0x09, 0xC4,
+0x00, 0x02, 0x09, 0x01, 0x18, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x02, 0x01, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, */
+};
+
+static void ide_init(struct device *dev)
+{
+ uint8_t enables, Rx89, RxC0;
+ u8 i, data;
+ struct ATA_REG_INIT_TABLE *pEntry;
+ printk_info("ide_init\n");
+
+#if 1
+ /*these 3 lines help to keep interl back door for DID VID SUBID untouched */
+ u16 data16_1, data16_2;
+ data16_1 = pci_read_config16(dev, 0xba);
+ data16_2 = pci_read_config16(dev, 0xbe);
+
+ for (i = 0; i < (16 * 12); i++) {
+ pci_write_config8(dev, 0x40 + i, idedevicepcitable[i]);
+ }
+ //pci_write_config8(dev, 0x0d, 0x20);
+ data = pci_read_config8(dev, 0x0d);
+ data &= 0x0f;
+ data |= 0x40;
+ pci_write_config8(dev, 0x0d, data);
+
+ //these 2 lines help to keep interl back door for DID VID SUBID untouched
+ pci_write_config16(dev, 0xba, data16_1);
+ pci_write_config16(dev, 0xbe, data16_2);
+#endif
+ /* Force interrupts to use compat mode. */
+ pci_write_config8(dev, PCI_INTERRUPT_PIN, 0x0);
+ pci_write_config8(dev, PCI_INTERRUPT_LINE, 0xff);
+#if 0
+
+
+
+ struct southbridge_via_vt8237r_config *sb =
+ (struct southbridge_via_vt8237r_config *) dev->chip_info;
+
+ u8 enables;
+ u32 cablesel;
+
+ pci_write_config16(dev, 0x04, 0x0007);
+
+ enables = pci_read_config8(dev, IDE_CS) & ~0x3;
+ enables |= 0x02;
+ pci_write_config8(dev, IDE_CS, enables);
+ enables = pci_read_config8(dev, IDE_CS);
+ printk_debug("Enables in reg 0x40 read back as 0x%x\n", enables);
+
+ /* Enable only compatibility mode. */
+ enables = pci_read_config8(dev, IDE_CONF_II);
+ enables &= ~0xc0;
+ pci_write_config8(dev, IDE_CONF_II, enables);
+ enables = pci_read_config8(dev, IDE_CONF_II);
+ printk_debug("Enables in reg 0x42 read back as 0x%x\n", enables);
+
+ /* Enable prefetch buffers. */
+ enables = pci_read_config8(dev, IDE_CONF_I);
+ enables |= 0xf0;
+ pci_write_config8(dev, IDE_CONF_I, enables);
+
+ /* Flush FIFOs at half. */
+ enables = pci_read_config8(dev, IDE_CONF_FIFO);
+ enables &= 0xf0;
+ enables |= (1 << 2) | (1 << 0);
+ pci_write_config8(dev, IDE_CONF_FIFO, enables);
+
+ /* PIO read prefetch counter, Bus Master IDE Status Reg. Read Retry. */
+ enables = pci_read_config8(dev, IDE_MISC_I);
+ enables &= 0xe2;
+ enables |= (1 << 4) | (1 << 3);
+ pci_write_config8(dev, IDE_MISC_I, enables);
+
+ /* Use memory read multiple, Memory-Write-and-Invalidate. */
+ enables = pci_read_config8(dev, IDE_MISC_II);
+ enables |= (1 << 2) | (1 << 3);
+ pci_write_config8(dev, IDE_MISC_II, enables);
+
+ /* Force interrupts to use compat mode. */
+ pci_write_config8(dev, PCI_INTERRUPT_PIN, 0x0);
+ pci_write_config8(dev, PCI_INTERRUPT_LINE, 0xff);
+
+ /* Cable guy... */
+ cablesel = pci_read_config32(dev, IDE_UDMA);
+ cablesel &= ~((1 << 28) | (1 << 20) | (1 << 12) | (1 << 4));
+ cablesel |= (sb->ide0_80pin_cable << 28) |
+ (sb->ide0_80pin_cable << 20) |
+ (sb->ide1_80pin_cable << 12) | (sb->ide1_80pin_cable << 4);
+ pci_write_config32(dev, IDE_UDMA, cablesel);
+#endif
+}
+
+static struct device_operations ide_ops = {
+ .read_resources = pci_dev_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .init = ide_init,
+ .enable = 0,
+ .ops_pci = 0,
+};
+
+static struct pci_driver via_ide_driver __pci_driver = {
+ .ops = &ide_ops,
+ .vendor = PCI_VENDOR_ID_VIA,
+ .device = PCI_DEVICE_ID_VIA_VX855_IDE,
+};
diff --git a/src/northbridge/via/vx800/vx800_lpc.c b/src/northbridge/via/vx800/vx800_lpc.c
new file mode 100644
index 0000000000..92660212cf
--- /dev/null
+++ b/src/northbridge/via/vx800/vx800_lpc.c
@@ -0,0 +1,384 @@
+/*
+ * 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
+ */
+
+#include <arch/io.h>
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ops.h>
+#include <device/pci_ids.h>
+
+#include <pc80/mc146818rtc.h>
+#include <pc80/keyboard.h>
+#include <pc80/i8259.h>
+#include "vx800.h"
+#include "chip.h"
+
+static const unsigned char pciIrqs[4] = {0xa, 0x9, 0xb, 0xa};
+
+static const unsigned char vgaPins[4] = { 'A', 'B', 'C', 'D' };//only INTA
+
+static const unsigned char slotPins[4] = { 'A', 'A', 'A', 'A'};//all 4
+
+static const unsigned char usbdevicePins[4] = { 'A', 'B', 'C', 'D' };//only INTA
+static const unsigned char sdioPins[4] = { 'A', 'B', 'C', 'D' };//only INTA
+static const unsigned char sd_ms_ctrl_Pins[4] = { 'B', 'C', 'D', 'A' };//only INTA
+static const unsigned char ce_ata_nf_ctrl_Pins[4] = { 'C', 'C', 'D', 'A' };//only INTA
+static const unsigned char idePins[4] = { 'B', 'C', 'D', 'A' };//only INTA
+
+static const unsigned char usbPins[4] = { 'A', 'B', 'C', 'D' };//all 4
+
+static const unsigned char hdacaudioPins[4] = { 'B', 'C', 'D', 'A' };//only INTA
+
+static unsigned char *pin_to_irq(const unsigned char *pin)
+{
+ static unsigned char Irqs[4];
+ int i;
+ for (i = 0 ; i < 4 ; i++)
+ Irqs[i] = pciIrqs[ pin[i] - 'A' ];
+
+ return Irqs;
+}
+
+static void pci_routing_fixup(struct device *dev)
+{
+ printk_info("%s: dev is %p\n", __FUNCTION__, dev);
+
+ /* set up PCI IRQ routing */
+ pci_write_config8(dev, 0x55, pciIrqs[0] << 4);
+ pci_write_config8(dev, 0x56, pciIrqs[1] | (pciIrqs[2] << 4) );
+ pci_write_config8(dev, 0x57, pciIrqs[3] << 4);
+
+ /* VGA */
+ printk_info("setting vga\n");
+ pci_assign_irqs(0, 0x1, pin_to_irq(vgaPins));
+
+ /* PCI slot */
+ printk_info("setting pci slot\n");
+ pci_assign_irqs(0, 0x08, pin_to_irq(slotPins));
+
+ /* PCI slot */
+ printk_info("setting USB Device Controller\n");
+ pci_assign_irqs(0, 0x0b, pin_to_irq(usbdevicePins));
+
+ /* PCI slot */
+ printk_info("setting SDIO Controller\n");
+ pci_assign_irqs(0, 0x0c, pin_to_irq(sdioPins));
+
+ /* PCI slot */
+ printk_info("setting SD $ MS Controller\n");
+ pci_assign_irqs(0, 0x0d, pin_to_irq(sd_ms_ctrl_Pins));
+
+ /* PCI slot */
+ printk_info("setting CE-ATA NF Controller(Card Boot)\n");
+ pci_assign_irqs(0, 0x0e, pin_to_irq(ce_ata_nf_ctrl_Pins));
+
+ /* PCI slot */
+ printk_info("setting ide\n");
+ //pci_assign_irqs(0, 0x0f, pin_to_irq(idePins));
+
+ /* Standard usb components */
+ printk_info("setting usb1-2\n");
+// pci_assign_irqs(0, 0x10, pin_to_irq(usbPins));
+
+ /* sound hardware */
+ printk_info("setting hdac audio\n");
+ pci_assign_irqs(0, 0x14, pin_to_irq(hdacaudioPins));
+
+ printk_spew("%s: DONE\n", __FUNCTION__);
+}
+
+void setup_pm(device_t dev)
+{
+ u16 tmp;
+ /* Debounce LID and PWRBTN# Inputs for 16ms. */
+ pci_write_config8(dev, 0x80, 0x20);
+
+ /* Set ACPI base address to IO VX800_ACPI_IO_BASE */
+ pci_write_config16(dev, 0x88, VX800_ACPI_IO_BASE|1);
+
+ /* set ACPI irq to 9 */
+ pci_write_config8(dev, 0x82, 0x49);
+
+ /* Primary interupt channel, define wake events 0=IRQ0 15=IRQ15 1=en. */
+// pci_write_config16(dev, 0x84, 0x30f2);
+ pci_write_config16(dev, 0x84, 0x609a); // 0x609a??
+
+ /* SMI output level to low, 7.5us throttle clock */
+ pci_write_config8(dev, 0x8d, 0x18);
+
+ /* GP Timer Control 1s */
+ pci_write_config8(dev, 0x93, 0x88);
+
+ /* Power Well */
+ pci_write_config8(dev, 0x94, 0x20); // 0x20??
+
+ /* 7 = stp to sust delay 1msec
+ * 6 = SUSST# Deasserted Before PWRGD for STD
+ */
+ pci_write_config8(dev, 0x95, 0xc0); // 0xc1??
+
+ /* Disable GP2 & GP3 Timer */
+ pci_write_config8(dev, 0x98, 0);
+
+ /* GP2 Timer Counter */
+ pci_write_config8(dev, 0x99, 0xfb);
+ /* GP3 Timer Counter */
+ //pci_write_config8(dev, 0x9a, 0x20);
+
+ /* Multi Function Select 1 */
+ pci_write_config8(dev, 0xe4, 0x00);
+ /* Multi Function Select 2 */
+ pci_write_config8(dev, 0xe5, 0x41); //??
+
+
+ /* Enable ACPI access (and setup like award) */
+ pci_write_config8(dev, 0x81, 0x84);
+
+ /* Clear status events. */
+ outw(0xffff, VX800_ACPI_IO_BASE + 0x00);
+ outw(0xffff, VX800_ACPI_IO_BASE + 0x20);
+ outw(0xffff, VX800_ACPI_IO_BASE + 0x28);
+ outl(0xffffffff, VX800_ACPI_IO_BASE + 0x30);
+
+ /* Disable SCI on GPIO. */
+ outw(0x0, VX800_ACPI_IO_BASE + 0x22);
+
+ /* Disable SMI on GPIO. */
+ outw(0x0, VX800_ACPI_IO_BASE + 0x24);
+
+ /* Disable all global enable SMIs. */
+ outw(0x0, VX800_ACPI_IO_BASE + 0x2a);
+
+ /* All SMI off, both IDE buses ON, PSON rising edge. */
+ outw(0x0, VX800_ACPI_IO_BASE + 0x2c);
+
+ /* Primary activity SMI disable. */
+ outl(0x0, VX800_ACPI_IO_BASE + 0x34);
+
+ /* GP timer reload on none. */
+ outl(0x0, VX800_ACPI_IO_BASE + 0x38);
+
+ /* Disable extended IO traps. */
+ outb(0x0, VX800_ACPI_IO_BASE + 0x42);
+
+ tmp = inw(VX800_ACPI_IO_BASE + 0x04);
+ /* SCI is generated for RTC/pwrBtn/slpBtn. */
+ tmp |= 1;
+ outw(tmp, VX800_ACPI_IO_BASE + 0x04);
+
+ /* Allow SLP# signal to assert LDTSTOP_L.
+ * Will work for C3 and for FID/VID change.
+ */
+ outb(0x1, VX800_ACPI_IO_BASE + 0x11);
+/*
+ outw(0x0, 0x424);
+ outw(0x0, 0x42a);
+ outw(0x1, 0x42c);
+ outl(0x0, 0x434);
+ outl(0x01, 0x438);
+ outb(0x0, 0x442);
+ outl(0xffff7fff, 0x448);
+ outw(0x001, 0x404);
+*/
+}
+void S3_ps2_kb_ms_wakeup(struct device *dev)
+{ u8 enables;
+ enables = pci_read_config8(dev, 0x51);
+ enables |= 2;
+ pci_write_config8(dev, 0x51, enables);
+
+ outb(0xe0, 0x2e);
+ outb(0x0b, 0x2f);//if 09,then only support kb wakeup
+
+ outb(0xe1, 0x2e);//set any key scan code can wakeup
+ outb(0x00, 0x2f);
+
+ outb(0xe9, 0x2e);//set any mouse scan code can wakeup
+ outb(0x00, 0x2f);
+
+ enables &= 0xd;
+ pci_write_config8(dev, 0x51, enables);
+
+ outb(inb(VX800_ACPI_IO_BASE+0x02)|0x20, VX800_ACPI_IO_BASE+0x02);//ACPI golabe enable for sci smi trigger
+ outw(inw(VX800_ACPI_IO_BASE+0x22)|0x204, VX800_ACPI_IO_BASE+0x22);//ACPI SCI on Internal KBC PME and mouse PME
+
+}
+void S3_usb_wakeup(struct device *dev)
+{
+ outw(inw(VX800_ACPI_IO_BASE+0x22)|0x4000, VX800_ACPI_IO_BASE+0x22);//SCI on USB PME
+}
+
+void S3_lid_wakeup(struct device *dev)
+{
+ outw(inw(VX800_ACPI_IO_BASE+0x22)|0x800, VX800_ACPI_IO_BASE+0x22);//SCI on LID PME
+}
+
+
+/* This looks good enough to work, maybe */
+static void vx800_sb_init(struct device *dev)
+{
+ unsigned char enables;
+
+ // enable the internal I/O decode
+ enables = pci_read_config8(dev, 0x6C);
+ enables |= 0x80;
+ pci_write_config8(dev, 0x6C, enables);
+
+ // Map 4MB of FLASH into the address space
+// pci_write_config8(dev, 0x41, 0x7f);
+
+ // Set bit 6 of 0x40, because Award does it (IO recovery time)
+ // IMPORTANT FIX - EISA 0x4d0 decoding must be on so that PCI
+ // interrupts can be properly marked as level triggered.
+ enables = pci_read_config8(dev, 0x40);
+ enables |= 0x44;
+ pci_write_config8(dev, 0x40, enables);
+
+ /* DMA Line buffer control */
+ enables = pci_read_config8(dev, 0x42);
+ enables |= 0xf0;
+ pci_write_config8(dev, 0x42, enables);
+
+ /* I/O recovery time */
+ pci_write_config8(dev, 0x4c, 0x44);
+
+ /* ROM memory cycles go to LPC. */
+ pci_write_config8(dev, 0x59, 0x80);
+
+ /* Set 0x5b to 0x01 to match Award */
+ //pci_write_config8(dev, 0x5b, 0x01);
+ enables = pci_read_config8(dev, 0x5b);
+ enables |= 0x01;
+ pci_write_config8(dev, 0x5b, enables);
+
+
+ /* Set Read Pass Write Control Enable */
+ pci_write_config8(dev, 0x48, 0x0c);
+
+ /* Set 0x58 to 0x42 APIC and RTC. */
+ //pci_write_config8(dev, 0x58, 0x42); this cmd cause the irq0 can not be triggerd,since bit 5 was set to 0.
+ enables=pci_read_config8(dev, 0x58);
+ enables|=0x41;//
+ pci_write_config8(dev, 0x58,enables);
+
+
+ /* Set bit 3 of 0x4f to match award (use INIT# as cpu reset) */
+ enables = pci_read_config8(dev, 0x4f);
+ enables |= 0x08;
+ pci_write_config8(dev, 0x4f, enables);
+
+ /* enable serial irq */
+ pci_write_config8(dev, 0x52, 0x9);
+
+ /* dma */
+ pci_write_config8(dev, 0x53, 0x00);
+
+ // Power management setup
+ setup_pm(dev);
+
+ /* set up isa bus -- i/o recovery time, rom write enable, extend-ale */
+ pci_write_config8(dev, 0x40, 0x54);
+
+ // Start the rtc
+ rtc_init(0);
+}
+
+/* total kludge to get lxb to call our childrens set/enable functions - these are
+ not called unless this device has a resource to set - so set a dummy one */
+void vx800_read_resources(device_t dev)
+{
+
+ struct resource *resource;
+ pci_dev_read_resources(dev);
+ resource = new_resource(dev, 1);
+ resource->flags |= IORESOURCE_FIXED | IORESOURCE_ASSIGNED | IORESOURCE_IO | IORESOURCE_STORED;
+ resource->size = 2;
+ resource->base = 0x2e;
+
+}
+void vx800_set_resources(device_t dev)
+{
+ struct resource *resource;
+ resource = find_resource(dev,1);
+ resource->flags |= IORESOURCE_STORED;
+ pci_dev_set_resources(dev);
+}
+
+void vx800_enable_resources(device_t dev)
+ {
+ /* vx800 is not a pci bridge and has no resources of its own (other than
+ standard PC i/o addresses). however it does control the isa bus and so
+ we need to manually call enable childrens resources on that bus */
+ /* TODO: do we even care about ISA? If so, for what? SuperIO on LPC bus */
+ pci_dev_enable_resources(dev);
+ enable_childrens_resources(dev);
+}
+
+static void southbridge_init(struct device *dev)
+{
+ printk_debug("vx800 sb init\n");
+ vx800_sb_init(dev);
+ pci_routing_fixup(dev);
+
+ setup_i8259(); // make sure interupt controller is configured before keyboard init
+
+ /* turn on keyboard and RTC, no need to visit this reg twice */
+ init_pc_keyboard(0x60, 0x64, 0);
+ printk_debug("ps2 usb lid, you set who can wakeup system from s3 sleep\n");
+ S3_ps2_kb_ms_wakeup(dev);
+ S3_usb_wakeup(dev);
+
+/* enable acpi cpu c3 state. (c2 state need not do anything.)
+ #1
+ fadt->pm2_cnt_blk = 0x22;//to support cpu-c3
+ fadt->p_lvl2_lat = 0x50; //this is the coreboot source
+ fadt->p_lvl3_lat = 0x320;//
+ fadt->pm2_cnt_len = 1;//to support cpu-c3
+ #2
+ ssdt? ->every cpu has a P_BLK address. set it to 0x10 (so that "Read Processor Level3 register(PMIORx15<7:0>) to enter C3 state"---VIA vx800 P SPEC )
+ #3 write 0x17 in to PMIO=VX800_ACPI_IO_BASE + 0x26, following the describtion in the P-spec.
+ 1 enable SLP# asserts in C3 state PMIORx26<1> =1
+ 2 enable CPUSTP# asserts in C3 state; PMIORx26<2> =1
+ 3 CLKRUN# is always asserted PMIORx26<3> =0
+ 4 Disable PCISTP# When CLKRUN# is asserted
+ 1: PCISTP# will not assert When CLKRUN# is asserted
+ PMIORx26<4> =1
+ 5 This bit controls whether the CPU voltage is lowered when in C3/S1 state.
+ VRDSLP will be active in either this bit set in C3 or LVL4 register read
+ PMIORx26<0> =0
+ 6 Read Processor Level3 register(PMIORx15<7:0>) to enter C3 state PMIORx15
+ */
+ outb(0x17, VX800_ACPI_IO_BASE + 0x26);
+
+}
+
+static struct device_operations vx800_lpc_ops = {
+ .read_resources = vx800_read_resources,
+ .set_resources = vx800_set_resources,
+ .enable_resources = vx800_enable_resources,
+ .init = &southbridge_init,
+ .scan_bus = scan_static_bus,
+};
+
+static struct pci_driver lpc_driver __pci_driver = {
+ .ops = &vx800_lpc_ops,
+ .vendor = PCI_VENDOR_ID_VIA,
+ .device = PCI_DEVICE_ID_VIA_VX855_LPC,
+};