Here's the VIA vx800 patch from OLPC.
authorBari Ari <bari@onelabs.com>
Wed, 27 May 2009 13:12:42 +0000 (13:12 +0000)
committerUwe Hermann <uwe@hermann-uwe.de>
Wed, 27 May 2009 13:12:42 +0000 (13:12 +0000)
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

36 files changed:
src/northbridge/via/vx800/Config.lb [new file with mode: 0644]
src/northbridge/via/vx800/DrivingClkPhaseData.h [new file with mode: 0644]
src/northbridge/via/vx800/chip.h [new file with mode: 0644]
src/northbridge/via/vx800/ddr2init/DramInit.c [new file with mode: 0644]
src/northbridge/via/vx800/ddr2init/DramInit.h [new file with mode: 0644]
src/northbridge/via/vx800/ddr2init/DramUtil.c [new file with mode: 0644]
src/northbridge/via/vx800/ddr2init/DramUtil.h [new file with mode: 0644]
src/northbridge/via/vx800/ddr2init/Translatorddr2init.c [new file with mode: 0644]
src/northbridge/via/vx800/ddr2init/vx800/ClkCtrl.c [new file with mode: 0644]
src/northbridge/via/vx800/ddr2init/vx800/DQSSearch.c [new file with mode: 0644]
src/northbridge/via/vx800/ddr2init/vx800/DRDY_BL.c [new file with mode: 0644]
src/northbridge/via/vx800/ddr2init/vx800/Detection.c [new file with mode: 0644]
src/northbridge/via/vx800/ddr2init/vx800/DevInit.c [new file with mode: 0644]
src/northbridge/via/vx800/ddr2init/vx800/DrivingSetting.c [new file with mode: 0644]
src/northbridge/via/vx800/ddr2init/vx800/FinalSetting.c [new file with mode: 0644]
src/northbridge/via/vx800/ddr2init/vx800/FreqSetting.c [new file with mode: 0644]
src/northbridge/via/vx800/ddr2init/vx800/RankMap.c [new file with mode: 0644]
src/northbridge/via/vx800/ddr2init/vx800/TimingSetting.c [new file with mode: 0644]
src/northbridge/via/vx800/ddr2init/vx800/UMARamSetting.c [new file with mode: 0644]
src/northbridge/via/vx800/examples/DrivingClkPhaseData.c [new file with mode: 0644]
src/northbridge/via/vx800/examples/cache_as_ram_auto.c [new file with mode: 0644]
src/northbridge/via/vx800/examples/chipset_init.c [new file with mode: 0644]
src/northbridge/via/vx800/northbridge.c [new file with mode: 0644]
src/northbridge/via/vx800/northbridge.h [new file with mode: 0644]
src/northbridge/via/vx800/raminit.c [new file with mode: 0644]
src/northbridge/via/vx800/raminit.h [new file with mode: 0644]
src/northbridge/via/vx800/romstrap.inc [new file with mode: 0644]
src/northbridge/via/vx800/romstrap.lds [new file with mode: 0644]
src/northbridge/via/vx800/vga.c [new file with mode: 0644]
src/northbridge/via/vx800/vgabios.c [new file with mode: 0644]
src/northbridge/via/vx800/vgachip.h [new file with mode: 0644]
src/northbridge/via/vx800/vx800.h [new file with mode: 0644]
src/northbridge/via/vx800/vx800_early_serial.c [new file with mode: 0644]
src/northbridge/via/vx800/vx800_early_smbus.c [new file with mode: 0644]
src/northbridge/via/vx800/vx800_ide.c [new file with mode: 0644]
src/northbridge/via/vx800/vx800_lpc.c [new file with mode: 0644]

diff --git a/src/northbridge/via/vx800/Config.lb b/src/northbridge/via/vx800/Config.lb
new file mode 100644 (file)
index 0000000..9e6fcfe
--- /dev/null
@@ -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 (file)
index 0000000..f6c8fea
--- /dev/null
@@ -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 (file)
index 0000000..700a398
--- /dev/null
@@ -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 (file)
index 0000000..ad4d721
--- /dev/null
@@ -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 (file)
index 0000000..36234bc
--- /dev/null
@@ -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 (file)
index 0000000..d09acda
--- /dev/null
@@ -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 (file)
index 0000000..725fd67
--- /dev/null
@@ -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 (file)
index 0000000..cb54aba
--- /dev/null
@@ -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 (file)
index 0000000..13edc1f
--- /dev/null
@@ -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 (file)
index 0000000..80749f8
--- /dev/null
@@ -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 (file)
index 0000000..b5a78f1
--- /dev/null
@@ -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 (file)
index 0000000..63fc56b
--- /dev/null
@@ -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 (file)
index 0000000..6a6ab22
--- /dev/null
@@ -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 (file)
index 0000000..3bdfdf3
--- /dev/null
@@ -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 (file)
index 0000000..165c887
--- /dev/null
@@ -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 (file)
index 0000000..ed4184e
--- /dev/null
@@ -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 (file)
index 0000000..f86a364
--- /dev/null
@@ -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 (file)
index 0000000..5e18478
--- /dev/null
@@ -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 (file)
index 0000000..f8aaf74
--- /dev/null
@@ -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 (file)
index 0000000..4028f02
--- /dev/null
@@ -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 (file)
index 0000000..5546851
--- /dev/null
@@ -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 (file)
index 0000000..d4e7e40
--- /dev/null
@@ -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 (file)
index 0000000..3d855ec
--- /dev/null
@@ -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 (file)
index 0000000..577efe6
--- /dev/null
@@ -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 (file)
index 0000000..58aef25
--- /dev/null
@@ -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 (file)
index 0000000..7885aa7
--- /dev/null
@@ -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 (file)
index 0000000..76c5e46
--- /dev/null
@@ -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 (file)
index 0000000..2e300c9
--- /dev/null
@@ -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 (file)
index 0000000..0368078
--- /dev/null
@@ -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 (file)
index 0000000..6155a79
--- /dev/null
@@ -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 (file)
index 0000000..86e948b
--- /dev/null
@@ -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 (file)
index 0000000..3955f1f
--- /dev/null
@@ -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 (file)
index 0000000..dfc5c3e
--- /dev/null
@@ -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 (file)
index 0000000..03deedc
--- /dev/null
@@ -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 (file)
index 0000000..4f9f8f9
--- /dev/null
@@ -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 (file)
index 0000000..9266021
--- /dev/null
@@ -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,
+};