Here's the VIA vx800 patch from OLPC.
It's untested, but a good starting point for everyone. Signed-off-by: Bari Ari <bari@onelabs.com> Acked-by: Ronald G. Minnich <rminnich@gmail.com> Acked-by: Uwe Hermann <uwe@hermann-uwe.de> git-svn-id: svn://svn.coreboot.org/coreboot/trunk@4313 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
This commit is contained in:
		
							
								
								
									
										25
									
								
								src/northbridge/via/vx800/Config.lb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/northbridge/via/vx800/Config.lb
									
									
									
									
									
										Normal file
									
								
							@@ -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
 | 
			
		||||
							
								
								
									
										70
									
								
								src/northbridge/via/vx800/DrivingClkPhaseData.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								src/northbridge/via/vx800/DrivingClkPhaseData.h
									
									
									
									
									
										Normal file
									
								
							@@ -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 */
 | 
			
		||||
							
								
								
									
										24
									
								
								src/northbridge/via/vx800/chip.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/northbridge/via/vx800/chip.h
									
									
									
									
									
										Normal file
									
								
							@@ -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;
 | 
			
		||||
							
								
								
									
										86
									
								
								src/northbridge/via/vx800/ddr2init/DramInit.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								src/northbridge/via/vx800/ddr2init/DramInit.c
									
									
									
									
									
										Normal file
									
								
							@@ -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;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										263
									
								
								src/northbridge/via/vx800/ddr2init/DramInit.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										263
									
								
								src/northbridge/via/vx800/ddr2init/DramInit.h
									
									
									
									
									
										Normal file
									
								
							@@ -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
 | 
			
		||||
							
								
								
									
										249
									
								
								src/northbridge/via/vx800/ddr2init/DramUtil.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										249
									
								
								src/northbridge/via/vx800/ddr2init/DramUtil.c
									
									
									
									
									
										Normal file
									
								
							@@ -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");
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										47
									
								
								src/northbridge/via/vx800/ddr2init/DramUtil.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								src/northbridge/via/vx800/ddr2init/DramUtil.h
									
									
									
									
									
										Normal file
									
								
							@@ -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
 | 
			
		||||
							
								
								
									
										34
									
								
								src/northbridge/via/vx800/ddr2init/Translatorddr2init.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								src/northbridge/via/vx800/ddr2init/Translatorddr2init.c
									
									
									
									
									
										Normal file
									
								
							@@ -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;
 | 
			
		||||
							
								
								
									
										312
									
								
								src/northbridge/via/vx800/ddr2init/vx800/ClkCtrl.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										312
									
								
								src/northbridge/via/vx800/ddr2init/vx800/ClkCtrl.c
									
									
									
									
									
										Normal file
									
								
							@@ -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);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										98
									
								
								src/northbridge/via/vx800/ddr2init/vx800/DQSSearch.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								src/northbridge/via/vx800/ddr2init/vx800/DQSSearch.c
									
									
									
									
									
										Normal file
									
								
							@@ -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);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										600
									
								
								src/northbridge/via/vx800/ddr2init/vx800/DRDY_BL.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										600
									
								
								src/northbridge/via/vx800/ddr2init/vx800/DRDY_BL.c
									
									
									
									
									
										Normal file
									
								
							@@ -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);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										192
									
								
								src/northbridge/via/vx800/ddr2init/vx800/Detection.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										192
									
								
								src/northbridge/via/vx800/ddr2init/vx800/Detection.c
									
									
									
									
									
										Normal file
									
								
							@@ -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;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1318
									
								
								src/northbridge/via/vx800/ddr2init/vx800/DevInit.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1318
									
								
								src/northbridge/via/vx800/ddr2init/vx800/DevInit.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										396
									
								
								src/northbridge/via/vx800/ddr2init/vx800/DrivingSetting.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										396
									
								
								src/northbridge/via/vx800/ddr2init/vx800/DrivingSetting.c
									
									
									
									
									
										Normal file
									
								
							@@ -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);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										129
									
								
								src/northbridge/via/vx800/ddr2init/vx800/FinalSetting.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								src/northbridge/via/vx800/ddr2init/vx800/FinalSetting.c
									
									
									
									
									
										Normal file
									
								
							@@ -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);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										235
									
								
								src/northbridge/via/vx800/ddr2init/vx800/FreqSetting.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										235
									
								
								src/northbridge/via/vx800/ddr2init/vx800/FreqSetting.c
									
									
									
									
									
										Normal file
									
								
							@@ -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");
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										363
									
								
								src/northbridge/via/vx800/ddr2init/vx800/RankMap.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										363
									
								
								src/northbridge/via/vx800/ddr2init/vx800/RankMap.c
									
									
									
									
									
										Normal file
									
								
							@@ -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;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										492
									
								
								src/northbridge/via/vx800/ddr2init/vx800/TimingSetting.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										492
									
								
								src/northbridge/via/vx800/ddr2init/vx800/TimingSetting.c
									
									
									
									
									
										Normal file
									
								
							@@ -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);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										445
									
								
								src/northbridge/via/vx800/ddr2init/vx800/UMARamSetting.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										445
									
								
								src/northbridge/via/vx800/ddr2init/vx800/UMARamSetting.c
									
									
									
									
									
										Normal file
									
								
							@@ -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
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										242
									
								
								src/northbridge/via/vx800/examples/DrivingClkPhaseData.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										242
									
								
								src/northbridge/via/vx800/examples/DrivingClkPhaseData.c
									
									
									
									
									
										Normal file
									
								
							@@ -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
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										660
									
								
								src/northbridge/via/vx800/examples/cache_as_ram_auto.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										660
									
								
								src/northbridge/via/vx800/examples/cache_as_ram_auto.c
									
									
									
									
									
										Normal file
									
								
							@@ -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");
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1298
									
								
								src/northbridge/via/vx800/examples/chipset_init.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1298
									
								
								src/northbridge/via/vx800/examples/chipset_init.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										247
									
								
								src/northbridge/via/vx800/northbridge.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										247
									
								
								src/northbridge/via/vx800/northbridge.c
									
									
									
									
									
										Normal file
									
								
							@@ -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,
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										25
									
								
								src/northbridge/via/vx800/northbridge.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/northbridge/via/vx800/northbridge.h
									
									
									
									
									
										Normal file
									
								
							@@ -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 */
 | 
			
		||||
							
								
								
									
										74
									
								
								src/northbridge/via/vx800/raminit.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								src/northbridge/via/vx800/raminit.c
									
									
									
									
									
										Normal file
									
								
							@@ -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");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										24
									
								
								src/northbridge/via/vx800/raminit.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/northbridge/via/vx800/raminit.h
									
									
									
									
									
										Normal file
									
								
							@@ -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 */
 | 
			
		||||
							
								
								
									
										51
									
								
								src/northbridge/via/vx800/romstrap.inc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								src/northbridge/via/vx800/romstrap.inc
									
									
									
									
									
										Normal file
									
								
							@@ -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
 | 
			
		||||
							
								
								
									
										26
									
								
								src/northbridge/via/vx800/romstrap.lds
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								src/northbridge/via/vx800/romstrap.lds
									
									
									
									
									
										Normal file
									
								
							@@ -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)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										148
									
								
								src/northbridge/via/vx800/vga.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										148
									
								
								src/northbridge/via/vx800/vga.c
									
									
									
									
									
										Normal file
									
								
							@@ -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,
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										862
									
								
								src/northbridge/via/vx800/vgabios.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										862
									
								
								src/northbridge/via/vx800/vgabios.c
									
									
									
									
									
										Normal file
									
								
							@@ -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;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										34
									
								
								src/northbridge/via/vx800/vgachip.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								src/northbridge/via/vx800/vgachip.h
									
									
									
									
									
										Normal file
									
								
							@@ -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 */
 | 
			
		||||
							
								
								
									
										125
									
								
								src/northbridge/via/vx800/vx800.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										125
									
								
								src/northbridge/via/vx800/vx800.h
									
									
									
									
									
										Normal file
									
								
							@@ -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
 | 
			
		||||
							
								
								
									
										110
									
								
								src/northbridge/via/vx800/vx800_early_serial.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										110
									
								
								src/northbridge/via/vx800/vx800_early_serial.c
									
									
									
									
									
										Normal file
									
								
							@@ -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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										321
									
								
								src/northbridge/via/vx800/vx800_early_smbus.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										321
									
								
								src/northbridge/via/vx800/vx800_early_smbus.c
									
									
									
									
									
										Normal file
									
								
							@@ -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
 | 
			
		||||
							
								
								
									
										204
									
								
								src/northbridge/via/vx800/vx800_ide.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										204
									
								
								src/northbridge/via/vx800/vx800_ide.c
									
									
									
									
									
										Normal file
									
								
							@@ -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,
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										384
									
								
								src/northbridge/via/vx800/vx800_lpc.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										384
									
								
								src/northbridge/via/vx800/vx800_lpc.c
									
									
									
									
									
										Normal file
									
								
							@@ -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,
 | 
			
		||||
};
 | 
			
		||||
		Reference in New Issue
	
	Block a user