Patchwork Fix AMD HD 3200 uma graphics problems in Win7 (revised)

login
register
about
Submitter Scott
Date 2010-11-03 04:29:10
Message ID <C030A2F7944A40AE9FC019041544BB6A@m3a78>
Download mbox | patch
Permalink /patch/2233/
State New
Headers show

Comments

Scott - 2010-11-03 04:29:10
(Re-submitting with correction to GFX debug bar setup procedure needed
for use with AMD family 0Fh processor).

This patch solves crashes and BSODs that occur when booting Win7 with
AMD RS780 uma graphics. Tested with frame buffer sizes 64m through 1GB
by running dxdiag and Windows media player at 1600x1200 true color.
Additional changes needed to boot Win7 on Mahogany_fam10 will follow.

-- Enable and program the debug bar as required by the ATI graphics driver.
   First, make the debug bar writable and allow resource allocation code
   to program it. Once programmed, enable its operation.
-- Disable the family 10h processor mmconf while the RS780 mmconf is in use.
-- Make strap programming more closely follow the reference BIOS.
-- Disable PCIe bar 3 after using it.
-- UMA size is no longer hardcoded.
-- Disable write combining for all steppings to eliminate stability problem.
-- Correct task file data.
-- Improve the accuracy of the Atom table that passes information to the driver.

Signed-off-by: Scott Duplichan <scott@notabs.org>
This patch solves crashes and BSODs that occur when booting Win7 with
AMD RS780 uma graphics. Tested with frame buffer sizes 64m through 1GB
by running dxdiag and Windows media player at 1600x1200 true color.
Additional changes needed to boot Win7 on Mahogany_fam10 will follow.

-- Enable and program the debug bar as required by the ATI graphics driver.
   First, make the debug bar writable and allow resource allocation code
   to program it. Once programmed, enable its operation.
-- Disable the family 10h processor mmconf while the RS780 mmconf is in use.
-- Make strap programming more closely follow the reference BIOS.
-- Disable PCIe bar 3 after using it.
-- UMA size is no longer hardcoded.
-- Disable write combining for all steppings to eliminate stability problem.
-- Correct task file data.
-- Improve the accuracy of the Atom table that passes information to the driver.

Signed-off-by: Scott Duplichan <scott@notabs.org>

Index: src/southbridge/amd/rs780/rs780.c
===================================================================
--- src/southbridge/amd/rs780/rs780.c	(revision 6011)
+++ src/southbridge/amd/rs780/rs780.c	(working copy)
@@ -133,11 +133,6 @@
 	temp32 = pci_read_config32(nb_dev, 0x4c);
 	printk(BIOS_DEBUG, "NB_PCI_REG4C = %x.\n", temp32);
 
-	/* disable GFX debug. */
-	temp8 = pci_read_config8(nb_dev, 0x8d);
-	temp8 &= ~(1<<1);
-	pci_write_config8(nb_dev, 0x8d, temp8);
-
 	/* set temporary NB TOM to 0x40000000. */
 	rs780_set_tom(nb_dev);
 
@@ -194,14 +189,24 @@
 static void rs780_nb_gfx_dev_table(device_t nb_dev, device_t dev)
 {
 	/* NB_InitGFXStraps */
-	u32 MMIOBase, apc04, apc18, apc24;
+	u32 MMIOBase, apc04, apc18, apc24, romstrap2;
+	msr_t pcie_mmio_save;
 	volatile u32 * strap;
 
+	// disable processor pcie mmio, if enabled
+	if (is_family10h()) {
+		msr_t temp;
+		pcie_mmio_save = temp = rdmsr (0xc0010058);
+		temp.lo &= ~1;
+		wrmsr (0xc0010058, temp);
+	}
+
 	/* Get PCIe configuration space. */
 	MMIOBase = pci_read_config32(nb_dev, 0x1c) & 0xfffffff0;
 	/* Temporarily disable PCIe configuration space. */
 	set_htiu_enable_bits(nb_dev, 0x32, 1<<28, 0);
 
+	// 1E: NB_BIF_SPARE
 	set_nbmisc_enable_bits(nb_dev, 0x1e, 0xffffffff, 1<<1 | 1<<4 | 1<<6 | 1<<7);
 	/* Set a temporary Bus number. */
 	apc18 = pci_read_config32(dev, 0x18);
@@ -214,18 +219,27 @@
 	pci_write_config8(dev, 0x04, 0x02);
 
 	/* Program Straps. */
-	strap = (volatile u32 *)(MMIOBase + 0x15020);
+	romstrap2 = 1 << 26; // enables audio function
 #if (CONFIG_GFXUMA == 1)
-	*strap = 1<<7; /* the format of BIF_MEM_AP_SIZE. 001->256MB? */
-#else
-	*strap = 0; /* 128M SP memory, 000 -> 128MB */
+	extern uint64_t uma_memory_size;
+	// bits 7-9: aperture size
+	// 0-7: 128mb, 256mb, 64mb, 32mb, 512mb, 1g, 2g, 4g 
+	if (uma_memory_size == 0x02000000) romstrap2 |= 3 << 7;
+	if (uma_memory_size == 0x04000000) romstrap2 |= 2 << 7;
+	if (uma_memory_size == 0x08000000) romstrap2 |= 0 << 7;
+	if (uma_memory_size == 0x10000000) romstrap2 |= 1 << 7;
+	if (uma_memory_size == 0x20000000) romstrap2 |= 4 << 7;
+	if (uma_memory_size == 0x40000000) romstrap2 |= 5 << 7;
+	if (uma_memory_size == 0x80000000) romstrap2 |= 6 << 7;
 #endif
+	strap = (volatile u32 *)(MMIOBase + 0x15020);
+	*strap = romstrap2;
 	strap = (volatile u32 *)(MMIOBase + 0x15000);
 	*strap = 0x2c006300;
 	strap = (volatile u32 *)(MMIOBase + 0x15010);
 	*strap = 0x03015330;
-	//strap = (volatile u32 *)(MMIOBase + 0x15020);
-	//*strap |= 0x00000040; /* Disable HDA device. */
+	strap = (volatile u32 *)(MMIOBase + 0x15020);
+	*strap = romstrap2 | 0x00000040;
 	strap = (volatile u32 *)(MMIOBase + 0x15030);
 	*strap = 0x00001002;
 	strap = (volatile u32 *)(MMIOBase + 0x15040);
@@ -240,8 +254,9 @@
 	/* BIF switches into normal functional mode. */
 	set_nbmisc_enable_bits(nb_dev, 0x1e, 1<<4 | 1<<5, 1<<5);
 
-	/* NB Revision is A12. */
-	set_nbmisc_enable_bits(nb_dev, 0x1e, 1<<9, 1<<9);
+	/* NB Revision is A12 or newer */
+	if (get_nb_rev(nb_dev) >= REV_RS780_A12)
+		set_nbmisc_enable_bits(nb_dev, 0x1e, 1<<9, 1<<9);
 
 	/* Restore APC04, APC18, APC24. */
 	pci_write_config32(dev, 0x04, apc04);
@@ -250,6 +265,11 @@
 
 	/* Enable PCIe configuration space. */
 	set_htiu_enable_bits(nb_dev, 0x32, 0, 1<<28);
+
+	// restore processor pcie mmio
+	if (is_family10h())
+		wrmsr (0xc0010058, pcie_mmio_save);
+
 	printk(BIOS_INFO, "GC is accessible from now on.\n");
 }
 
@@ -332,18 +352,17 @@
 				       (dev->enabled ? 1 : 0) << 6);
 		if (dev->enabled)
 			rs780_gpp_sb_init(nb_dev, dev, dev_ind);
-		disable_pcie_bar3(nb_dev);
 		break;
 	case 9:		/* bus 0, dev 9,10, GPP */
 	case 10:
 		printk(BIOS_INFO, "Bus-0, Dev-9, 10, Fun-0. enable=%d\n",
 			    dev->enabled);
-		enable_pcie_bar3(nb_dev);	/* PCIEMiscInit */
 		set_nbmisc_enable_bits(nb_dev, 0x0c, 1 << (7 + dev_ind),
 				       (dev->enabled ? 0 : 1) << (7 + dev_ind));
 		if (dev->enabled)
 			rs780_gpp_sb_init(nb_dev, dev, dev_ind);
-		/* Dont call disable_pcie_bar3(nb_dev) here, otherwise the screen will crash. */
+
+		if (dev_ind == 10) disable_pcie_bar3(nb_dev);
 		break;
 	default:
 		printk(BIOS_DEBUG, "unknown dev: %s\n", dev_path(dev));
Index: src/southbridge/amd/rs780/rs780.h
===================================================================
--- src/southbridge/amd/rs780/rs780.h	(revision 6011)
+++ src/southbridge/amd/rs780/rs780.h	(working copy)
@@ -208,4 +208,9 @@
 void config_gpp_core(device_t nb_dev, device_t sb_dev);
 void PcieReleasePortTraining(device_t nb_dev, device_t dev, u32 port);
 u8 PcieTrainPort(device_t nb_dev, device_t dev, u32 port);
+u32 extractbit(u32 data, int bit_number);
+u32 extractbits(u32 source, int lsb, int msb);
+int cpuidFamily(void);
+int is_family0Fh(void);
+int is_family10h(void);
 #endif				/* RS780_H */
Index: src/southbridge/amd/rs780/rs780_cmn.c
===================================================================
--- src/southbridge/amd/rs780/rs780_cmn.c	(revision 6011)
+++ src/southbridge/amd/rs780/rs780_cmn.c	(working copy)
@@ -29,6 +29,7 @@
 #include <cpu/amd/mtrr.h>
 #include <boot/coreboot_tables.h>
 #include <delay.h>
+#include <cpu/cpu.h>
 #include "rs780.h"
 
 static u32 nb_read_index(device_t dev, u32 index_reg, u32 index)
@@ -223,7 +224,7 @@
 		pci_write_config32(k8_f1, 0xbc, 0);
 		pci_write_config32(k8_f1, 0xb0, 0);
 		pci_write_config32(k8_f1, 0xb4, 0);
-	}
+	}
 }
 
 void PcieReleasePortTraining(device_t nb_dev, device_t dev, u32 port)
@@ -361,3 +362,42 @@
 	pci_write_config32(nb_dev, 0x90, uma_memory_base);
 	//nbmc_write_index(nb_dev, 0x1e, uma_memory_base);
 }
+
+// extract single bit
+u32 extractbit(u32 data, int bit_number)
+{
+	return (data >> bit_number) & 1;
+}
+
+// extract bit field
+u32 extractbits(u32 source, int lsb, int msb)
+{
+	int field_width = msb - lsb + 1;
+	u32 mask = 0xFFFFFFFF >> (32 - field_width);
+	return (source >> lsb) & mask;
+}
+
+// return AMD cpuid family
+int cpuidFamily(void)
+{
+	u32 baseFamily, extendedFamily, fms;
+	
+	fms = cpuid_eax (1);
+	baseFamily = extractbits (fms, 8, 11);
+	extendedFamily = extractbits (fms, 20, 27);
+	return baseFamily + extendedFamily;
+}
+
+
+// return non-zero for AMD family 0Fh processor found
+int is_family0Fh(void)
+{
+	return cpuidFamily() == 0x0F;
+}
+
+
+// return non-zero for AMD family 10h processor found
+int is_family10h(void)
+{
+	return cpuidFamily() == 0x10;
+}
Index: src/southbridge/amd/rs780/rs780_early_setup.c
===================================================================
--- src/southbridge/amd/rs780/rs780_early_setup.c	(revision 6011)
+++ src/southbridge/amd/rs780/rs780_early_setup.c	(working copy)
@@ -483,9 +483,11 @@
 	/* Reg94h[31:29] = 0x7 Enables HT transmitter de-emphasis */
 	set_nbcfg_enable_bits_8(nb_dev, 0x97, (u8)(~0x1F), 0xE0);
 
-	/*Reg8Ch[10:9] = 0x3 Enables Gfx Debug BAR,
-	 * force this BAR as mem type in rs780_gfx.c */
-	set_nbcfg_enable_bits_8(nb_dev, 0x8D, (u8)(~0xFF), 0x03);
+	/* Reg8Ch[9] enables Gfx Debug BAR programming
+	 * Reg8Ch[10] enables Gfx Debug BAR operation
+	 * Enable programming of the debug bar now, but enable
+	 * operation only after it has been programmed */
+	set_nbcfg_enable_bits_8(nb_dev, 0x8D, (u8)(~0xFF), 0x02);
 }
 
 static void rs780_por_mc_index_init(device_t nb_dev)
Index: src/southbridge/amd/rs780/rs780_gfx.c
===================================================================
--- src/southbridge/amd/rs780/rs780_gfx.c	(revision 6011)
+++ src/southbridge/amd/rs780/rs780_gfx.c	(working copy)
@@ -39,6 +39,8 @@
 void set_pcie_reset(void);
 void set_pcie_dereset(void);
 
+extern uint64_t uma_memory_base, uma_memory_size;
+
 /* Trust the original resource allocation. Don't do it again. */
 #undef DONT_TRUST_RESOURCE_ALLOCATION
 //#define DONT_TRUST_RESOURCE_ALLOCATION
@@ -304,11 +306,15 @@
 	volatile u32 * pointer;
 	int i;
 	u16 command;
-	u32 value, sblk;
+	u32 value;
 	u16 deviceid, vendorid;
 	device_t nb_dev = dev_find_slot(0, 0);
 	device_t k8_f2 = dev_find_slot(0, PCI_DEVFN(0x18, 2));
 	device_t k8_f0 = dev_find_slot(0, PCI_DEVFN(0x18, 0));
+	static u8 ht_freq_lookup [] = {2, 0, 4, 0, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 0, 0, 28, 30, 32};
+	static u8 ht_width_lookup [] = {8, 16, 0, 0, 2, 4, 0, 0};
+	static u16 memclk_lookup_fam0F [] = {100, 0, 133, 0, 0, 166, 0, 200};
+	static u16 memclk_lookup_fam10 [] = {200, 266, 333, 400, 533, 667, 800, 800};
 
 	/* We definetely will use this in future. Just leave it here. */
 	/*struct southbridge_amd_rs780_config *cfg =
@@ -339,6 +345,8 @@
 	*(GpuF0MMReg + 0x2180/4) = ((value&0xff00)>>8)|((value&0xff000000)>>8);
 	*(GpuF0MMReg + 0x2c04/4) = ((value&0xff00)<<8);
 	*(GpuF0MMReg + 0x5428/4) = ((value&0xffff0000)+0x10000)-((value&0xffff)<<16);
+	*(GpuF0MMReg + 0xF774/4) = 0xffffffff;
+	*(GpuF0MMReg + 0xF770/4) = 0x00000001;
 	*(GpuF0MMReg + 0x2000/4) = 0x00000011;
 	*(GpuF0MMReg + 0x200c/4) = 0x00000020;
 	*(GpuF0MMReg + 0x2010/4) = 0x10204810;
@@ -352,21 +360,26 @@
 	*(GpuF0MMReg + 0x7de4/4) |= (1<<3) | (1<<4);
 	/* Force allow LDT_STOP Cool'n'Quiet workaround. */
 	*(GpuF0MMReg + 0x655c/4) |= 1<<4;
+
+	// disable write combining, needed for stability
+	*(GpuF0MMReg + 0x2000/4) = 0x00000010;
+	*(GpuF0MMReg + 0x2408/4) = 1 << 9;
+	*(GpuF0MMReg + 0x2000/4) = 0x00000011;
+
 	/* GFX_InitFBAccess finished. */
 
+#if (CONFIG_GFXUMA == 1) /* for UMA mode. */
 	/* GFX_StartMC. */
-#if (CONFIG_GFXUMA == 1) /* for UMA mode. */
-	/* MC_INIT_COMPLETE. */
-	set_nbmc_enable_bits(nb_dev, 0x2, 0, 1<<31);
-	/* MC_STARTUP, MC_POWERED_UP and MC_VMODE.*/
-	set_nbmc_enable_bits(nb_dev, 0x1, 1<<18, 1|1<<2);
-
-	set_nbmc_enable_bits(nb_dev, 0xb1, 0, 1<<6);
-	set_nbmc_enable_bits(nb_dev, 0xc3, 0, 1);
-	nbmc_write_index(nb_dev, 0x07, 0x18);
-	nbmc_write_index(nb_dev, 0x06, 0x00000102);
-	nbmc_write_index(nb_dev, 0x09, 0x40000008);
-	set_nbmc_enable_bits(nb_dev, 0x6, 0, 1<<31);
+	set_nbmc_enable_bits(nb_dev, 0x02, 0x00000000, 0x80000000);
+	set_nbmc_enable_bits(nb_dev, 0x01, 0x00000000, 0x00000001);
+	set_nbmc_enable_bits(nb_dev, 0x01, 0x00000000, 0x00000004);
+	set_nbmc_enable_bits(nb_dev, 0x01, 0x00040000, 0x00000000);
+	set_nbmc_enable_bits(nb_dev, 0xB1, 0xFFFF0000, 0x00000040);
+	set_nbmc_enable_bits(nb_dev, 0xC3, 0x00000000, 0x00000001);
+	set_nbmc_enable_bits(nb_dev, 0x07, 0xFFFFFFFF, 0x00000018);
+	set_nbmc_enable_bits(nb_dev, 0x06, 0xFFFFFFFF, 0x00000102);
+	set_nbmc_enable_bits(nb_dev, 0x09, 0xFFFFFFFF, 0x40000008);
+	set_nbmc_enable_bits(nb_dev, 0x06, 0x00000000, 0x80000000);
 	/* GFX_StartMC finished. */
 #else
 	/* for SP mode. */
@@ -418,77 +431,110 @@
 	vgainfo.sHeader.ucTableContentRevision = 2;
 
 #if (CONFIG_GFXUMA == 0) /* SP mode. */
+	// Side port support is incomplete, do not use it
+	// These parameters must match the motherboard
 	vgainfo.ulBootUpSidePortClock = 667*100;
-	vgainfo.ucMemoryType = 3;
+	vgainfo.ucMemoryType = 3;  // 3=ddr3 sp mem, 2=ddr2 sp mem
 	vgainfo.ulMinSidePortClock = 333*100;
 #endif
 
-	vgainfo.ulBootUpEngineClock = 500 * 100; /* set boot up GFX engine clock. */
-	vgainfo.ulReserved1[0] = 0;	vgainfo.ulReserved1[1] = 0;
-	value = pci_read_config32(k8_f2, 0x94);
-	printk(BIOS_DEBUG, "MEMCLK = %x\n", value&0x7);
-	vgainfo.ulBootUpUMAClock = 333 * 100; /* set boot up UMA memory clock. */
-	vgainfo.ulBootUpSidePortClock = 0; /* disable SP. */
-	vgainfo.ulMinSidePortClock = 0; /* disable SP. */
-	for(i=0; i<6; i++)
-		vgainfo.ulReserved2[i] = 0;
-	vgainfo.ulSystemConfig = 0;
-	//vgainfo.ulSystemConfig |= 1<<1 | 1<<3 | 1<<4 | 1<<5 | 1<<6 | 1<<7 | 1;
-	vgainfo.ulBootUpReqDisplayVector = 0; //?
-	vgainfo.ulOtherDisplayMisc = 0; //?
-	vgainfo.ulDDISlot1Config = 0x000c0011; //0; //VGA
-	//vgainfo.ulDDISlot1Config = 0x000c00FF; //0; //HDMI
-	vgainfo.ulDDISlot2Config = 0x00130022; //0; //?
-	vgainfo.ucMemoryType = 2;
-	/* UMA Channel Number: 1 or 2. */
-	vgainfo.ucUMAChannelNumber = 2;
-	vgainfo.ucDockingPinBit = 0; //?
-	vgainfo.ucDockingPinPolarity = 0; //?
-	vgainfo.ulDockingPinCFGInfo = 0; //?
-	vgainfo.ulCPUCapInfo = 3; /* K8. */
+	vgainfo.ulBootUpEngineClock = 500 * 100;	       	// setup option on reference BIOS, 500 is default
 
-	/* page 5-19 on BDG. */
-	vgainfo.usNumberOfCyclesInPeriod = 0x8019;
-	vgainfo.usMaxNBVoltage = 0x1a;
-	vgainfo.usMinNBVoltage = 0;
-	vgainfo.usBootUpNBVoltage = 0x1a;
+	// find the DDR memory frequency
+	if (is_family10h()) {
+		value = pci_read_config32(k8_f2, 0x94);		// read channel 0 DRAM Configuration High Register
+		if (extractbit(value, 14))			// if channel 0 disabled, channel 1 must have memory
+			value = pci_read_config32(k8_f2, 0x194);// read channel 1 DRAM Configuration High Register
+		vgainfo.ulBootUpUMAClock = memclk_lookup_fam10 [extractbits (value, 0, 2)] * 100;
+	}
+	if (is_family0Fh()) {
+		value = pci_read_config32(k8_f2, 0x94);
+		vgainfo.ulBootUpUMAClock = memclk_lookup_fam0F [extractbits (value, 20, 22)] * 100;
+	}
 
-	/* Get SBLink value (HyperTransport I/O Hub Link ID). */
-	value = pci_read_config32(k8_f0, 0x64);
-	sblk = (value >> 8) & 0x3;
-	printk(BIOS_DEBUG, "SBLINK = %d.\n", sblk);
+	/* UMA Channel Number: 1 or 2. */
+	vgainfo.ucUMAChannelNumber = 1;
+	if (is_family0Fh()) {
+		value = pci_read_config32(k8_f2, 0x90);
+	if (extractbit(value, 11))  // 128-bit mode
+		vgainfo.ucUMAChannelNumber = 2;
+	}
+	if (is_family10h()) {
+		u32 dch0 = pci_read_config32(k8_f2, 0x94);
+		u32 dch1 = pci_read_config32(k8_f2, 0x194);
+		if (extractbit(dch0, 14) == 0 && extractbit(dch1, 14) == 0) { // both channels enabled
+			value = pci_read_config32(k8_f2, 0x110);
+			if (extractbit(value, 4))  // ganged mode
+			vgainfo.ucUMAChannelNumber = 2;
+		}
+	}
+      
+	// processor type
+	if (is_family0Fh())
+		vgainfo.ulCPUCapInfo = 3;
+	if (is_family10h())
+		vgainfo.ulCPUCapInfo = 2;
 
 	/* HT speed */
-	value = pci_read_config32(nb_dev, 0xd0);
-	printk(BIOS_DEBUG, "NB HT speed = %x.\n", value);
-	value = pci_read_config32(k8_f0, 0x88 + (sblk * 0x20));
-	printk(BIOS_DEBUG, "CPU HT speed = %x.\n", value);
-	vgainfo.ulHTLinkFreq = 100 * 100; /* set HT speed. */
+	value = pci_read_config8(nb_dev, 0xd1);
+	value = ht_freq_lookup [value] * 100;  // HT link frequency in MHz
+	vgainfo.ulHTLinkFreq = value * 100;    // HT frequency in units of 100 MHz
+	vgainfo.ulHighVoltageHTLinkFreq = vgainfo.ulHTLinkFreq;
+	vgainfo.ulLowVoltageHTLinkFreq = vgainfo.ulHTLinkFreq;
 
+	if (value <= 1800)
+		vgainfo.ulLowVoltageHTLinkFreq = vgainfo.ulHTLinkFreq;
+	else {
+		int sblink, cpuLnkFreqCap, nbLnkFreqCap;
+		value = pci_read_config32(k8_f0, 0x64);
+		sblink = extractbits(value, 8, 10);
+		cpuLnkFreqCap = pci_read_config16(k8_f0, 0x8a + sblink * 0x20);
+		nbLnkFreqCap = pci_read_config16(nb_dev, 0xd2);
+		if (cpuLnkFreqCap & nbLnkFreqCap & (1 << 10)) // if both 1800 MHz capable
+		vgainfo.ulLowVoltageHTLinkFreq = 1800*100;
+	}
+
 	/* HT width. */
-	value = pci_read_config32(nb_dev, 0xc8);
-	printk(BIOS_DEBUG, "HT width = %x.\n", value);
-	vgainfo.usMinHTLinkWidth = 16;
-	vgainfo.usMaxHTLinkWidth = 16;
-	vgainfo.usUMASyncStartDelay = 322;
-	vgainfo.usUMADataReturnTime = 86;
-	vgainfo.usLinkStatusZeroTime = 0x00c8; //0; //?
-	vgainfo.usReserved = 0;
-	vgainfo.ulHighVoltageHTLinkFreq = 100 * 100;
-	vgainfo.ulLowVoltageHTLinkFreq = 100 * 100;
-	vgainfo.usMaxUpStreamHTLinkWidth = 16;
-	vgainfo.usMaxDownStreamHTLinkWidth = 16;
-	vgainfo.usMinUpStreamHTLinkWidth = 16;
-	vgainfo.usMinDownStreamHTLinkWidth = 16;
-	for(i=0; i<97; i++)
-		vgainfo.ulReserved3[i] = 0;
+	value = pci_read_config8(nb_dev, 0xcb);
+	vgainfo.usMinDownStreamHTLinkWidth = 
+	vgainfo.usMaxDownStreamHTLinkWidth = 
+	vgainfo.usMinUpStreamHTLinkWidth = 
+	vgainfo.usMaxUpStreamHTLinkWidth =
+	vgainfo.usMinHTLinkWidth =
+	vgainfo.usMaxHTLinkWidth = ht_width_lookup [extractbits(value, 0, 2)];
 
+	if (is_family0Fh()) {
+		vgainfo.usUMASyncStartDelay = 322;
+		vgainfo.usUMADataReturnTime = 286;
+	}
+
+	if (is_family10h()) {
+		static u16 t0mult_lookup [] = {10, 50, 200, 2000};
+		int t0time, t0scale;
+		value = pci_read_config32(k8_f0, 0x16c);
+		t0time = extractbits(value, 0, 3);
+		t0scale = extractbits(value, 4, 5);
+		vgainfo.usLinkStatusZeroTime = t0mult_lookup [t0scale] * t0time;
+		vgainfo.usUMASyncStartDelay = 100;
+		if (vgainfo.ulHTLinkFreq < 1000 * 100) { // less than 1000 MHz
+			vgainfo.usUMADataReturnTime = 300;
+			vgainfo.usLinkStatusZeroTime = 6 * 100;   // 6us for GH in HT1 mode
+		}
+		else {
+			int lssel;
+			value = pci_read_config32(nb_dev, 0xac);
+			lssel = extractbits (value, 7, 8);
+			vgainfo.usUMADataReturnTime = 1300;
+			if (lssel == 0) vgainfo.usUMADataReturnTime = 150;
+		}
+	}
+
 	/* Transfer the Table to VBIOS. */
 	pointer = (u32 *)&vgainfo;
 	for(i=0; i<sizeof(ATOM_INTEGRATED_SYSTEM_INFO_V2); i+=4)
 	{
 #if (CONFIG_GFXUMA == 1)
-		*GpuF0MMReg = 0x80000000 + 0x10000000 - 512 + i;
+		*GpuF0MMReg = 0x80000000 + uma_memory_size - 512 + i;
 #else
 		*GpuF0MMReg = 0x80000000 + 0x8000000 - 512 + i;
 #endif
@@ -497,11 +543,22 @@
 
 	/* GFX_InitLate. */
 	{
-		u8 temp8;
-		temp8 = pci_read_config8(dev, 0x4);
-		//temp8 &= ~1; /* CIM clears this bit. Strangely, I can'd. */
-		temp8 |= 1<<1|1<<2;
-		pci_write_config8(dev, 0x4, temp8);
+		u32 temp;
+		temp = pci_read_config8(dev, 0x4);
+		//temp &= ~1; /* CIM clears this bit. Strangely, I can'd. */
+		temp |= 1<<1|1<<2;
+		pci_write_config8(dev, 0x4, temp);
+
+		// if the GFX debug bar is writable, then it has
+		// been programmed and can be safely enabled now
+		temp = pci_read_config32(nb_dev, 0x8c);
+
+		// if bits 1 (intgfx_enable) and 9 (gfx_debug_bar_enable)
+		// then enable gfx debug bar (set gxf_debug_decode_enable)
+		if (temp & 0x202)
+			temp |= (1 << 10);
+		pci_write_config32(nb_dev, 0x8c, temp);
+
 	}
 
 #ifdef DONT_TRUST_RESOURCE_ALLOCATION
@@ -584,7 +641,6 @@
 * Set registers in RS780 and CPU to enable the internal GFX.
 * Please refer to CIM source code and BKDG.
 */
-extern uint64_t uma_memory_base, uma_memory_size;
 
 static void rs780_internal_gfx_enable(device_t dev)
 {
@@ -637,7 +693,9 @@
 #if (CONFIG_GFXUMA == 1)
 	/* GFX_InitUMA. */
 	/* Copy CPU DDR Controller to NB MC. */
+	device_t k8_f1 = dev_find_slot(0, PCI_DEVFN(0x18, 1));
 	device_t k8_f2 = dev_find_slot(0, PCI_DEVFN(0x18, 2));
+	device_t k8_f4 = dev_find_slot(0, PCI_DEVFN(0x18, 4));
 	for (i = 0; i < 12; i++)
 	{
 		l_dword = pci_read_config32(k8_f2, 0x40 + i * 4);
@@ -646,24 +704,40 @@
 
 	l_dword = pci_read_config32(k8_f2, 0x80);
 	nbmc_write_index(nb_dev, 0x3c, l_dword);
-
 	l_dword = pci_read_config32(k8_f2, 0x94);
-	if(l_dword & (1<<22))
-		set_nbmc_enable_bits(nb_dev, 0x3c, 0, 1<<16);
-	else
-		set_nbmc_enable_bits(nb_dev, 0x3c, 1<<16, 0);
+	set_nbmc_enable_bits(nb_dev, 0x3c, 0, !!(l_dword & (1<<22))<<16);
+	set_nbmc_enable_bits(nb_dev, 0x3c, 0, !!(l_dword & (1<< 8))<<17);
+	l_dword = pci_read_config32(k8_f2, 0x90);
+	set_nbmc_enable_bits(nb_dev, 0x3c, 0, !!(l_dword & (1<<10))<<18);
+   if (is_family10h())
+   {
+	   for (i = 0; i < 12; i++)
+	   {
+		   l_dword = pci_read_config32(k8_f2, 0x140 + i * 4);
+		   nbmc_write_index(nb_dev, 0x3d + i, l_dword);
+	   }
 
-	if(l_dword & (1<<8))
-		set_nbmc_enable_bits(nb_dev, 0x3c, 0, 1<<17);
-	else
-		set_nbmc_enable_bits(nb_dev, 0x3c, 1<<17, 0);
+	   l_dword = pci_read_config32(k8_f2, 0x180);
+	   nbmc_write_index(nb_dev, 0x49, l_dword);
+	   l_dword = pci_read_config32(k8_f2, 0x194);
+	   set_nbmc_enable_bits(nb_dev, 0x49, 0, !!(l_dword & (1<<22))<<16);
+	   set_nbmc_enable_bits(nb_dev, 0x49, 0, !!(l_dword & (1<< 8))<<17);
+	   l_dword = pci_read_config32(k8_f2, 0x190);
+	   set_nbmc_enable_bits(nb_dev, 0x49, 0, !!(l_dword & (1<<10))<<18);
 
-	l_dword = pci_read_config32(k8_f2, 0x90);
-	if(l_dword & (1<<10))
-		set_nbmc_enable_bits(nb_dev, 0x3c, 0, 1<<18);
-	else
-		set_nbmc_enable_bits(nb_dev, 0x3c, 1<<18, 0);
+	   l_dword = pci_read_config32(k8_f2, 0x110);
+	   nbmc_write_index(nb_dev, 0x4a, l_dword);
+	   l_dword = pci_read_config32(k8_f2, 0x114);
+	   nbmc_write_index(nb_dev, 0x4b, l_dword);
+	   l_dword = pci_read_config32(k8_f4, 0x44);
+	   set_nbmc_enable_bits(nb_dev, 0x4a, 0, !!(l_dword & (1<<22))<<24);
+	   l_dword = pci_read_config32(k8_f1, 0x40);
+	   nbmc_write_index(nb_dev, 0x4c, l_dword);
+	   l_dword = pci_read_config32(k8_f1, 0xf0);
+	   nbmc_write_index(nb_dev, 0x4d, l_dword);
+   }
 
+
 	/* Set UMA in the 780 side. */
 	/* UMA start address, size. */
 	/* The UMA starts at 0xC0000000 of internal RS780 address space
@@ -672,7 +746,7 @@
 	nbmc_write_index(nb_dev, 0x10, ((uma_memory_size - 1 + 0xC0000000) & (~0xffff)) | 0xc000);
 	nbmc_write_index(nb_dev, 0x11, uma_memory_base);
 	nbmc_write_index(nb_dev, 0x12, 0);
-	nbmc_write_index(nb_dev, 0xf0, 256);
+	nbmc_write_index(nb_dev, 0xf0, uma_memory_size >> 20);
 	/* GFX_InitUMA finished. */
 #else
 	/* GFX_InitSP. */
@@ -1016,7 +1090,7 @@
 	/* 5.9.1.1. Disables the GFX REFCLK transmitter so that the GFX
 	 * REFCLK PAD can be driven by an external source. */
 	/* 5.9.1.2. Enables GFX REFCLK receiver to receive the REFCLK from an external source. */
-	set_nbmisc_enable_bits(nb_dev, 0x38, 1 << 29 | 1 << 28, 0 << 29 | 1 << 28);
+	set_nbmisc_enable_bits(nb_dev, 0x38, 1 << 29 | 1 << 28 | 1 << 26, 1 << 28);
 
 	/* 5.9.1.3 Selects the GFX REFCLK to be the source for PLL A. */
 	/* 5.9.1.4 Selects the GFX REFCLK to be the source for PLL B. */
Index: src/southbridge/amd/rs780/rs780_pcie.c
===================================================================
--- src/southbridge/amd/rs780/rs780_pcie.c	(revision 6011)
+++ src/southbridge/amd/rs780/rs780_pcie.c	(working copy)
@@ -221,6 +221,7 @@
 	printk(BIOS_DEBUG, "disable_pcie_bar3()\n");
 	pci_write_config32(nb_dev, 0x1C, 0);	/* clear BAR3 address */
 	set_nbcfg_enable_bits(nb_dev, 0x7C, 1 << 30, 0 << 30);	/* Disable writes to the BAR3. */
+	set_htiu_enable_bits(nb_dev, 0x32, 1 << 28, 0);	/* disable bar3 decode */
 	ProgK8TempMmioBase(0, EXT_CONF_BASE_ADDRESS, TEMP_MMIO_BASE_ADDRESS);
 }
Carl-Daniel Hailfinger - 2010-11-03 18:14:09
Hi Scott,

I am not totally convinced that all changes are a net win.

On 03.11.2010 05:29, Scott Duplichan wrote:
> (Re-submitting with correction to GFX debug bar setup procedure needed
> for use with AMD family 0Fh processor).
>
> This patch solves crashes and BSODs that occur when booting Win7 with
> AMD RS780 uma graphics. Tested with frame buffer sizes 64m through 1GB
> by running dxdiag and Windows media player at 1600x1200 true color.
> Additional changes needed to boot Win7 on Mahogany_fam10 will follow.
>
> -- Enable and program the debug bar as required by the ATI graphics driver.
>    First, make the debug bar writable and allow resource allocation code
>    to program it. Once programmed, enable its operation.
>   

Good.


> -- Disable the family 10h processor mmconf while the RS780 mmconf is in use.
>   

I thought the family 10h processors need their own MMCONF for some
configuration accesses. If this disable happens after all such config
writes are done, I'm OK with it.


> -- Make strap programming more closely follow the reference BIOS.
>   

Good.


> -- Disable PCIe bar 3 after using it.
>   

This one is something I have reservations about. Isn't PCIe BAR 3 the
one via which MMCONF accesses are done? How is MMCONF going to work
after that?


> -- UMA size is no longer hardcoded.
>   

Nice.


> -- Disable write combining for all steppings to eliminate stability problem.
>   

This may have a performance impact, right? Do you know if any steppings
with stable write combining exist?


> -- Correct task file data.
> -- Improve the accuracy of the Atom table that passes information to the driver.
>   

Yes, that's definitely needed.


> Signed-off-by: Scott Duplichan <scott@notabs.org>
>   

I think the patch looks good, but I'd like a few answers before I ack it.

Regards,
Carl-Daniel
Scott - 2010-11-03 21:17:35
-----Original Message-----
From: Carl-Daniel Hailfinger [mailto:c-d.hailfinger.devel.2006@gmx.net] 
Sent: Wednesday, November 03, 2010 01:14 PM
To: Scott Duplichan
Cc: coreboot@coreboot.org
Subject: Re: [coreboot] [PATCH] Fix AMD HD 3200 uma graphics problems in Win7 (revised)

]Hi Scott,
]
]I am not totally convinced that all changes are a net win.

Hello Carl-Daniel,

Thanks for looking at it. The strategy I used is to try to make the code
match the current AMD CIMx code as closely as possible. The existing RS780
code is based on an older CIMx version that does not support the family 10h
processor. I actually did many experiments with a reference BIOS as a way
to find what parts of the code are essential for getting Win7 booted. It is
interesting to know that much of the code is not needed for Win7 boot or
even for video playback using windows media player. An example is the code
that copies some of the processor memory controller settings to the RS780.
What is this code for then? Possibly it becomes important for some directX
or 3D operation that I did not exercise. I did not test any 3D application.

]On 03.11.2010 05:29, Scott Duplichan wrote:
]> (Re-submitting with correction to GFX debug bar setup procedure needed
]> for use with AMD family 0Fh processor).
]>
]> This patch solves crashes and BSODs that occur when booting Win7 with
]> AMD RS780 uma graphics. Tested with frame buffer sizes 64m through 1GB
]> by running dxdiag and Windows media player at 1600x1200 true color.
]> Additional changes needed to boot Win7 on Mahogany_fam10 will follow.
]>
]> -- Enable and program the debug bar as required by the ATI graphics driver.
]>    First, make the debug bar writable and allow resource allocation code
]>    to program it. Once programmed, enable its operation.
]>   
]
]Good.
]
]
]> -- Disable the family 10h processor mmconf while the RS780 mmconf is in use.
]>   
]
]I thought the family 10h processors need their own MMCONF for some
]configuration accesses. If this disable happens after all such config
]writes are done, I'm OK with it.

The family 10h mmconf is disabled only temporarily, then restored to its
previous state. I added this code because that is how the current CIMx
code does it.

]> -- Make strap programming more closely follow the reference BIOS.
]>   
]
]Good.
]
]
]> -- Disable PCIe bar 3 after using it.
]>   
]
]This one is something I have reservations about. Isn't PCIe BAR 3 the
]one via which MMCONF accesses are done? How is MMCONF going to work
]after that?

Of the two reference BIOS binaries I can boot, neither appears to leave
PCIe bar 3 enabled. I see zeros there after booting, although I am not
100% sure this means zero is its real value. Yet on the two reference BIOS
images, along with the patched coreboot, I can still see the RS780 at
mmconf+0. I assume the family 10h processor sends mmconf requests to
the HT link if the address is not that of an internal device. I don't
know how it works for family 0Fh processors. 

The original coreboot RS780 code intended to disable BAR 3 after using
it. The code comment reads, "We should disable bar3 when we want to exit
rs780_enable, because bar3 will be remapped in set_resource later".
However, the call to the disable function was removed and replaced by
this comment: "Don't call disable_pcie_bar3(nb_dev) here, otherwise the
screen will crash". I debugged this problem and found the disable function
set the bar to zero, but did not disable it. So legacy video MMIO writes
were being claimed by bar 3 and not reaching the video function. The patch
corrects this problem and adds back the function call to disable bar 3 after
PCIe training is complete. The reason I even looked at this code in the
first place is this. With the unpatched code, the PCI resource allocation
code finds bar 3 writable and assigns it a base address. In my case it
assigned C0000000. This C000000 range is unusable because it is not the
range set aside for mmconf. I have mmconf at F8000000.

In addition, I noticed the mahogany_fam10 and mahogany projects have no
MCFG table, so Windows will never use mmconf for PCI config access. This
is an area I would like to study more, but any improvement should probably
be done in a separate patch. It is interesting to know that Microsoft
planned for mmconf and the ACPI MCFG table to be required for Windows Vista.
The early beta editions required it. But it proved too much trouble and
the requirement was removed. The requirement was not added back for Win7.
I don't know if it is planned for Win8.

]> -- UMA size is no longer hardcoded.
]>   
]
]Nice.
]
]
]> -- Disable write combining for all steppings to eliminate stability problem.
]>   
]
]This may have a performance impact, right? Do you know if any steppings
]with stable write combining exist?

Write combining should only be disabled for the early steppings. Why
I have to disable it for A13 is an unsolved problem. Yes, I would assume
there is a performance impact. On the otherhand, using the ATI driver with
write combining disabled still gives a big performance boost when compared
to the generic vga driver. I would like to solve this problem, but have run
out of time for the moment.


]> -- Correct task file data.
]> -- Improve the accuracy of the Atom table that passes information to the driver.
]>   
]
]Yes, that's definitely needed.
]
]
]> Signed-off-by: Scott Duplichan <scott@notabs.org>
]>   
]
]I think the patch looks good, but I'd like a few answers before I ack it.
]
]Regards,
]Carl-Daniel
Rudolf Marek - 2010-11-03 21:34:29
Hi Scott,

I tried to boot with that on famF CPU and it went well.
ruiktest:~#
ruiktest:~# lspci -vvv -s 01:05.0

01:05.0 VGA compatible controller: ATI Technologies Inc RS880 [Radeon HD 4200] 
(prog-if 00 [VGA controller])
	Subsystem: ATI Technologies Inc Device 0000
	Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- 
SERR- FastB2B- DisINTx-
	Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- 
<MAbort- >SERR- <PERR- INTx-
	Latency: 0, Cache Line Size: 64 bytes
	Interrupt: pin A routed to IRQ 18
	Region 0: Memory at e8000000 (32-bit, prefetchable) [size=128M]
	Region 1: I/O ports at 1000 [size=256]
	Region 2: Memory at f8100000 (32-bit, non-prefetchable) [size=64K]
	Region 5: Memory at f8000000 (32-bit, non-prefetchable) [size=1M]
	Expansion ROM at <unassigned> [disabled]
	Capabilities: [50] Power Management version 3
		Flags: PMEClk- DSI- D1+ D2+ AuxCurrent=0mA PME(D0-,D1-,D2-,D3hot-,D3cold-)
		Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=0 PME-
	Capabilities: [a0] MSI: Enable- Count=1/1 Maskable- 64bit+
		Address: 0000000000000000  Data: 0000
	Kernel driver in use: radeon

The BAR seems to be enabled. Btw I tried to boot Win7 but still got only logo 
animation forever. Not sure what it could be.

I agree that this patch is big improvement. We can fix the MMCONF later.

Thanks,
Rudolf
Marc Jones - 2010-11-03 23:52:42
On Wed, Nov 3, 2010 at 3:34 PM, Rudolf Marek <r.marek@assembler.cz> wrote:
> Hi Scott,
>
> I tried to boot with that on famF CPU and it went well.
> ruiktest:~#
> ruiktest:~# lspci -vvv -s 01:05.0
>
> 01:05.0 VGA compatible controller: ATI Technologies Inc RS880 [Radeon HD
> 4200] (prog-if 00 [VGA controller])
>        Subsystem: ATI Technologies Inc Device 0000
>        Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr-
> Stepping- SERR- FastB2B- DisINTx-
>        Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort-
> <TAbort- <MAbort- >SERR- <PERR- INTx-
>        Latency: 0, Cache Line Size: 64 bytes
>        Interrupt: pin A routed to IRQ 18
>        Region 0: Memory at e8000000 (32-bit, prefetchable) [size=128M]
>        Region 1: I/O ports at 1000 [size=256]
>        Region 2: Memory at f8100000 (32-bit, non-prefetchable) [size=64K]
>        Region 5: Memory at f8000000 (32-bit, non-prefetchable) [size=1M]
>        Expansion ROM at <unassigned> [disabled]
>        Capabilities: [50] Power Management version 3
>                Flags: PMEClk- DSI- D1+ D2+ AuxCurrent=0mA
> PME(D0-,D1-,D2-,D3hot-,D3cold-)
>                Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=0 PME-
>        Capabilities: [a0] MSI: Enable- Count=1/1 Maskable- 64bit+
>                Address: 0000000000000000  Data: 0000
>        Kernel driver in use: radeon
>
> The BAR seems to be enabled. Btw I tried to boot Win7 but still got only
> logo animation forever. Not sure what it could be.
>
> I agree that this patch is big improvement. We can fix the MMCONF later.

Was that an ack?

Maybe I misunderstand, but I don't think that there is an MMCONF
issue. The bar disable prevents the 780 MMCONF from being moved,
right?

Just curious, have you test this with Linux? I tried to load win7, but
got a ACPI stop 0xA5. I suspect that my tables are not working at all.
This is on iei kino. I will investigate more tomorrow.

Marc
Peter Stuge - 2010-11-04 09:24:13
Scott Duplichan wrote:
> With the unpatched code, the PCI resource allocation code finds bar
> 3 writable and assigns it a base address. In my case it assigned
> C0000000. This C000000 range is unusable because it is not the
> range set aside for mmconf. I have mmconf at F8000000.

Do we need a parameter for the resource allocator to know if a
resource should go within or outside mmconf?


//Peter
Arne Georg Gleditsch - 2010-11-04 09:37:36
"Scott Duplichan" <scott@notabs.org> writes:
> -- Disable the family 10h processor mmconf while the RS780 mmconf is in use.

I'm not sure I understand how this is supposed to work.  Shouldn't we
just make sure the two mmconf regions don't overlap?  (Or is the overlap
intended?)  To be frank, I'm not sure what the RS780 mmconf offers over
the Fam10 mmconf at all.  For Fam0f, I assume it is useful in order to
reach extended config space, but as far as I know that should be covered
by the Fam10 mmconf already.

> +	// disable processor pcie mmio, if enabled
> +	if (is_family10h()) {
> +		msr_t temp;
> +		pcie_mmio_save = temp = rdmsr (0xc0010058);
> +		temp.lo &= ~1;
> +		wrmsr (0xc0010058, temp);
> +	}
> +
>  	/* Get PCIe configuration space. */
>  	MMIOBase = pci_read_config32(nb_dev, 0x1c) & 0xfffffff0;

This pci_read_config32 is targeting the Fam10 mmconf area, which is now
disabled.  Are we relying on the rs780 mmconf to back this address
region at this point?  If so, we probably should take care to make sure
the address assignments match (or rather, document that they need to
match).  If we need to do this at all, that is.

>  	/* Temporarily disable PCIe configuration space. */
>  	set_htiu_enable_bits(nb_dev, 0x32, 1<<28, 0);

But here we disable the rs780 mmconf, no?  Who's backing the mmconf
address region now:

> +	// 1E: NB_BIF_SPARE
>  	set_nbmisc_enable_bits(nb_dev, 0x1e, 0xffffffff, 1<<1 | 1<<4 | 1<<6 | 1<<7);
>  	/* Set a temporary Bus number. */
>  	apc18 = pci_read_config32(dev, 0x18);

?

Apologies if I have misunderstood something, I haven't quite kept up
with the discussion.  I'm just a bit concerned about these changes.
Scott - 2010-11-04 16:03:20
-----Original Message-----
From: coreboot-bounces@coreboot.org [mailto:coreboot-bounces@coreboot.org] On Behalf Of Arne Georg Gleditsch
Sent: Thursday, November 04, 2010 04:38 AM
To: Scott Duplichan
Cc: 'Peter Stuge'; 'Carl-Daniel Hailfinger'; coreboot@coreboot.org
Subject: Re: [coreboot] [PATCH] Fix AMD HD 3200 uma graphics problems inWin7 (revised)

"Scott Duplichan" <scott@notabs.org> writes:
> -- Disable the family 10h processor mmconf while the RS780 mmconf is in use.

]I'm not sure I understand how this is supposed to work.  Shouldn't we
]just make sure the two mmconf regions don't overlap?  (Or is the overlap
]intended?)  To be frank, I'm not sure what the RS780 mmconf offers over
]the Fam10 mmconf at all.  For Fam0f, I assume it is useful in order to
]reach extended config space, but as far as I know that should be covered
]by the Fam10 mmconf already.

No doubt there different, and possibly simpler, ways to make this work.
The patch I submitted attempts to follow the method used by the AMD CIMx
reference code. 

]> +	// disable processor pcie mmio, if enabled
]> +	if (is_family10h()) {
]> +		msr_t temp;
]> +		pcie_mmio_save = temp = rdmsr (0xc0010058);
]> +		temp.lo &= ~1;
]> +		wrmsr (0xc0010058, temp);
]> +	}
]> +
]>  	/* Get PCIe configuration space. */
]>  	MMIOBase = pci_read_config32(nb_dev, 0x1c) & 0xfffffff0;
]
]This pci_read_config32 is targeting the Fam10 mmconf area, which is now
]disabled.  Are we relying on the rs780 mmconf to back this address
]region at this point?

When I step through this pci_read_config32 call (on simnow) I see it using
the cf8/cfc method for config access, not the mmio method.

]If so, we probably should take care to make sure
]the address assignments match (or rather, document that they need to
]match).  If we need to do this at all, that is.
]
]>  	/* Temporarily disable PCIe configuration space. */
]>  	set_htiu_enable_bits(nb_dev, 0x32, 1<<28, 0);
]
]But here we disable the rs780 mmconf, no?  Who's backing the mmconf
]address region now:

Again it looks like all config space access is done with cf8/cfc for
these calls.

]
]> +	// 1E: NB_BIF_SPARE
]>  	set_nbmisc_enable_bits(nb_dev, 0x1e, 0xffffffff, 1<<1 | 1<<4 | 1<<6 | 1<<7);
]>  	/* Set a temporary Bus number. */
]>  	apc18 = pci_read_config32(dev, 0x18);
]
]?
]
]Apologies if I have misunderstood something, I haven't quite kept up
]with the discussion.  I'm just a bit concerned about these changes.
]-- 
]								Arne.
Arne Georg Gleditsch - 2010-11-04 17:16:25
"Scott Duplichan" <scott@notabs.org> writes:
> When I step through this pci_read_config32 call (on simnow) I see it using
> the cf8/cfc method for config access, not the mmio method.

Ok, that sounds like CONFIG_MMCONF_SUPPORT_DEFAULT is not set, is that
right?  Presuming that's so, I'm worried that this code will break for
boards where MMCONFIG is enabled per default.
Marc Jones - 2010-11-04 17:34:41
On Thu, Nov 4, 2010 at 10:03 AM, Scott Duplichan <scott@notabs.org> wrote:
> -----Original Message-----

> ]> +    // disable processor pcie mmio, if enabled
> ]> +    if (is_family10h()) {
> ]> +            msr_t temp;
> ]> +            pcie_mmio_save = temp = rdmsr (0xc0010058);
> ]> +            temp.lo &= ~1;
> ]> +            wrmsr (0xc0010058, temp);
> ]> +    }
> ]> +
> ]>      /* Get PCIe configuration space. */
> ]>      MMIOBase = pci_read_config32(nb_dev, 0x1c) & 0xfffffff0;
> ]
> ]This pci_read_config32 is targeting the Fam10 mmconf area, which is now
> ]disabled.  Are we relying on the rs780 mmconf to back this address
> ]region at this point?
>
> When I step through this pci_read_config32 call (on simnow) I see it using
> the cf8/cfc method for config access, not the mmio method.


This should be MMCONF with CONFIG_MMCONF_SUPPORT=y. Is that not the
case? Did we miss something?

Marc
Scott - 2010-11-04 18:42:38
-----Original Message-----
From: Marc Jones [mailto:marcj303@gmail.com] 
Sent: Thursday, November 04, 2010 12:35 PM
To: Scott Duplichan
Cc: Arne Georg Gleditsch; Peter Stuge; Carl-Daniel Hailfinger; coreboot@coreboot.org
Subject: Re: [coreboot] [PATCH] Fix AMD HD 3200 uma graphics problems inWin7 (revised)

]On Thu, Nov 4, 2010 at 10:03 AM, Scott Duplichan <scott@notabs.org> wrote:
]> -----Original Message-----
]
]> ]> +    // disable processor pcie mmio, if enabled
]> ]> +    if (is_family10h()) {
]> ]> +            msr_t temp;
]> ]> +            pcie_mmio_save = temp = rdmsr (0xc0010058);
]> ]> +            temp.lo &= ~1;
]> ]> +            wrmsr (0xc0010058, temp);
]> ]> +    }
]> ]> +
]> ]>      /* Get PCIe configuration space. */
]> ]>      MMIOBase = pci_read_config32(nb_dev, 0x1c) & 0xfffffff0;
]> ]
]> ]This pci_read_config32 is targeting the Fam10 mmconf area, which is now
]> ]disabled.  Are we relying on the rs780 mmconf to back this address
]> ]region at this point?
]>
]> When I step through this pci_read_config32 call (on simnow) I see it using
]> the cf8/cfc method for config access, not the mmio method.
]
]
]This should be MMCONF with CONFIG_MMCONF_SUPPORT=y. Is that not the
]case? Did we miss something?

Yes, CONFIG_MMCONF_SUPPORT=y for my test. OK, so let's step through
pci_write_config32(). That sould be simple enough, probably 3 or 4
processor instructions? It turns out 112 instructions with the 
optimized build! Anyway, pci_read_config32() first calls get_pbus(dev).
In the context above, get_pbus(dev) returns null. It then passes this
null pointer to ops_pci_bus, which falls back to the cf8/cfc method
because that is what pci_check_direct() found to work. I believe for
whatever reasons, the fallback code is used for early execution. Once
execution reaches post code 40, the mmconf method is used.

Thanks,
Scott

]Marc
]
]
]-- 
]http://se-eng.com
Arne Georg Gleditsch - 2010-11-04 19:25:28
"Scott Duplichan" <scott@notabs.org> writes:
> Yes, CONFIG_MMCONF_SUPPORT=y for my test.

This only indicates whether support for the mmconf facility should be
compiled in.  If CONFIG_MMCONF_SUPPORT_DEFAULT isn't also set, you'll
only be using the mmconf facility if you explicitly do
pci_mmconf_read_config32 or similar.
Scott - 2010-11-04 21:29:50
-----Original Message-----
From: Arne Georg Gleditsch [mailto:arne@gledits.ch] On Behalf Of Arne Georg Gleditsch
Sent: Thursday, November 04, 2010 02:25 PM
To: Scott Duplichan
Cc: 'Marc Jones'; 'Peter Stuge'; 'Carl-Daniel Hailfinger'; coreboot@coreboot.org
Subject: Re: [PATCH] Fix AMD HD 3200 uma graphics problems inWin7 (revised)

"Scott Duplichan" <scott@notabs.org> writes:
> Yes, CONFIG_MMCONF_SUPPORT=y for my test.

]This only indicates whether support for the mmconf facility should be
]compiled in.  If CONFIG_MMCONF_SUPPORT_DEFAULT isn't also set, you'll
]only be using the mmconf facility if you explicitly do
]pci_mmconf_read_config32 or similar.

Hello Arne,

That is a good point. Here are the relevant items from my config.h:
#define CONFIG_MMCONF_BUS_NUMBER 16
#define CONFIG_MMCONF_SUPPORT 1
#define CONFIG_MMCONF_BASE_ADDRESS 0xf8000000
#define CONFIG_MMCONF_SUPPORT_DEFAULT 1

]-- 
							Arne.
Arne Georg Gleditsch - 2010-11-04 22:14:33
"Scott Duplichan" <scott@notabs.org> writes:
> Hello Arne,
>
> That is a good point. Here are the relevant items from my config.h:
> #define CONFIG_MMCONF_BUS_NUMBER 16
> #define CONFIG_MMCONF_SUPPORT 1
> #define CONFIG_MMCONF_BASE_ADDRESS 0xf8000000
> #define CONFIG_MMCONF_SUPPORT_DEFAULT 1

My apologies, I went back and followed your email re pci_write_config32
step through properly, and of course you're right.  In this context this
doesn't really matter, since the pci_ops_mmconf selected by the fam10
northbridge are not invoked.  So provided we're not (inadvertently)
making config space accesses that do so, switching the mapping around
should be fairly safe.

(That said, if these accesses are not touching that address region, what
accesses are?  If none actually do, switching the mapping around
wouldn't really seem to accomplish much?  Anyway, it seems my
understanding of this particular code is less complete than I thought,
so I'll butt out of this discussion for now.)
Rudolf Marek - 2010-11-23 22:42:53
> Was that an ack?

Now it is Acked-by: Rudolf Marek <r.marek@assembler.cz>

Without this patch I got blank screen after KMS sets the mode.

Thanks,
Rudolf

Patch

Index: src/southbridge/amd/rs780/rs780.c
===================================================================
--- src/southbridge/amd/rs780/rs780.c	(revision 6011)
+++ src/southbridge/amd/rs780/rs780.c	(working copy)
@@ -133,11 +133,6 @@ 
 	temp32 = pci_read_config32(nb_dev, 0x4c);
 	printk(BIOS_DEBUG, "NB_PCI_REG4C = %x.\n", temp32);
 
-	/* disable GFX debug. */
-	temp8 = pci_read_config8(nb_dev, 0x8d);
-	temp8 &= ~(1<<1);
-	pci_write_config8(nb_dev, 0x8d, temp8);
-
 	/* set temporary NB TOM to 0x40000000. */
 	rs780_set_tom(nb_dev);
 
@@ -194,14 +189,24 @@ 
 static void rs780_nb_gfx_dev_table(device_t nb_dev, device_t dev)
 {
 	/* NB_InitGFXStraps */
-	u32 MMIOBase, apc04, apc18, apc24;
+	u32 MMIOBase, apc04, apc18, apc24, romstrap2;
+	msr_t pcie_mmio_save;
 	volatile u32 * strap;
 
+	// disable processor pcie mmio, if enabled
+	if (is_family10h()) {
+		msr_t temp;
+		pcie_mmio_save = temp = rdmsr (0xc0010058);
+		temp.lo &= ~1;
+		wrmsr (0xc0010058, temp);
+	}
+
 	/* Get PCIe configuration space. */
 	MMIOBase = pci_read_config32(nb_dev, 0x1c) & 0xfffffff0;
 	/* Temporarily disable PCIe configuration space. */
 	set_htiu_enable_bits(nb_dev, 0x32, 1<<28, 0);
 
+	// 1E: NB_BIF_SPARE
 	set_nbmisc_enable_bits(nb_dev, 0x1e, 0xffffffff, 1<<1 | 1<<4 | 1<<6 | 1<<7);
 	/* Set a temporary Bus number. */
 	apc18 = pci_read_config32(dev, 0x18);
@@ -214,18 +219,27 @@ 
 	pci_write_config8(dev, 0x04, 0x02);
 
 	/* Program Straps. */
-	strap = (volatile u32 *)(MMIOBase + 0x15020);
+	romstrap2 = 1 << 26; // enables audio function
 #if (CONFIG_GFXUMA == 1)
-	*strap = 1<<7; /* the format of BIF_MEM_AP_SIZE. 001->256MB? */
-#else
-	*strap = 0; /* 128M SP memory, 000 -> 128MB */
+	extern uint64_t uma_memory_size;
+	// bits 7-9: aperture size
+	// 0-7: 128mb, 256mb, 64mb, 32mb, 512mb, 1g, 2g, 4g 
+	if (uma_memory_size == 0x02000000) romstrap2 |= 3 << 7;
+	if (uma_memory_size == 0x04000000) romstrap2 |= 2 << 7;
+	if (uma_memory_size == 0x08000000) romstrap2 |= 0 << 7;
+	if (uma_memory_size == 0x10000000) romstrap2 |= 1 << 7;
+	if (uma_memory_size == 0x20000000) romstrap2 |= 4 << 7;
+	if (uma_memory_size == 0x40000000) romstrap2 |= 5 << 7;
+	if (uma_memory_size == 0x80000000) romstrap2 |= 6 << 7;
 #endif
+	strap = (volatile u32 *)(MMIOBase + 0x15020);
+	*strap = romstrap2;
 	strap = (volatile u32 *)(MMIOBase + 0x15000);
 	*strap = 0x2c006300;
 	strap = (volatile u32 *)(MMIOBase + 0x15010);
 	*strap = 0x03015330;
-	//strap = (volatile u32 *)(MMIOBase + 0x15020);
-	//*strap |= 0x00000040; /* Disable HDA device. */
+	strap = (volatile u32 *)(MMIOBase + 0x15020);
+	*strap = romstrap2 | 0x00000040;
 	strap = (volatile u32 *)(MMIOBase + 0x15030);
 	*strap = 0x00001002;
 	strap = (volatile u32 *)(MMIOBase + 0x15040);
@@ -240,8 +254,9 @@ 
 	/* BIF switches into normal functional mode. */
 	set_nbmisc_enable_bits(nb_dev, 0x1e, 1<<4 | 1<<5, 1<<5);
 
-	/* NB Revision is A12. */
-	set_nbmisc_enable_bits(nb_dev, 0x1e, 1<<9, 1<<9);
+	/* NB Revision is A12 or newer */
+	if (get_nb_rev(nb_dev) >= REV_RS780_A12)
+		set_nbmisc_enable_bits(nb_dev, 0x1e, 1<<9, 1<<9);
 
 	/* Restore APC04, APC18, APC24. */
 	pci_write_config32(dev, 0x04, apc04);
@@ -250,6 +265,11 @@ 
 
 	/* Enable PCIe configuration space. */
 	set_htiu_enable_bits(nb_dev, 0x32, 0, 1<<28);
+
+	// restore processor pcie mmio
+	if (is_family10h())
+		wrmsr (0xc0010058, pcie_mmio_save);
+
 	printk(BIOS_INFO, "GC is accessible from now on.\n");
 }
 
@@ -332,18 +352,17 @@ 
 				       (dev->enabled ? 1 : 0) << 6);
 		if (dev->enabled)
 			rs780_gpp_sb_init(nb_dev, dev, dev_ind);
-		disable_pcie_bar3(nb_dev);
 		break;
 	case 9:		/* bus 0, dev 9,10, GPP */
 	case 10:
 		printk(BIOS_INFO, "Bus-0, Dev-9, 10, Fun-0. enable=%d\n",
 			    dev->enabled);
-		enable_pcie_bar3(nb_dev);	/* PCIEMiscInit */
 		set_nbmisc_enable_bits(nb_dev, 0x0c, 1 << (7 + dev_ind),
 				       (dev->enabled ? 0 : 1) << (7 + dev_ind));
 		if (dev->enabled)
 			rs780_gpp_sb_init(nb_dev, dev, dev_ind);
-		/* Dont call disable_pcie_bar3(nb_dev) here, otherwise the screen will crash. */
+
+		if (dev_ind == 10) disable_pcie_bar3(nb_dev);
 		break;
 	default:
 		printk(BIOS_DEBUG, "unknown dev: %s\n", dev_path(dev));
Index: src/southbridge/amd/rs780/rs780.h
===================================================================
--- src/southbridge/amd/rs780/rs780.h	(revision 6011)
+++ src/southbridge/amd/rs780/rs780.h	(working copy)
@@ -208,4 +208,9 @@ 
 void config_gpp_core(device_t nb_dev, device_t sb_dev);
 void PcieReleasePortTraining(device_t nb_dev, device_t dev, u32 port);
 u8 PcieTrainPort(device_t nb_dev, device_t dev, u32 port);
+u32 extractbit(u32 data, int bit_number);
+u32 extractbits(u32 source, int lsb, int msb);
+int cpuidFamily(void);
+int is_family0Fh(void);
+int is_family10h(void);
 #endif				/* RS780_H */
Index: src/southbridge/amd/rs780/rs780_cmn.c
===================================================================
--- src/southbridge/amd/rs780/rs780_cmn.c	(revision 6011)
+++ src/southbridge/amd/rs780/rs780_cmn.c	(working copy)
@@ -29,6 +29,7 @@ 
 #include <cpu/amd/mtrr.h>
 #include <boot/coreboot_tables.h>
 #include <delay.h>
+#include <cpu/cpu.h>
 #include "rs780.h"
 
 static u32 nb_read_index(device_t dev, u32 index_reg, u32 index)
@@ -223,7 +224,7 @@ 
 		pci_write_config32(k8_f1, 0xbc, 0);
 		pci_write_config32(k8_f1, 0xb0, 0);
 		pci_write_config32(k8_f1, 0xb4, 0);
-	}
+	}
 }
 
 void PcieReleasePortTraining(device_t nb_dev, device_t dev, u32 port)
@@ -361,3 +362,42 @@ 
 	pci_write_config32(nb_dev, 0x90, uma_memory_base);
 	//nbmc_write_index(nb_dev, 0x1e, uma_memory_base);
 }
+
+// extract single bit
+u32 extractbit(u32 data, int bit_number)
+{
+	return (data >> bit_number) & 1;
+}
+
+// extract bit field
+u32 extractbits(u32 source, int lsb, int msb)
+{
+	int field_width = msb - lsb + 1;
+	u32 mask = 0xFFFFFFFF >> (32 - field_width);
+	return (source >> lsb) & mask;
+}
+
+// return AMD cpuid family
+int cpuidFamily(void)
+{
+	u32 baseFamily, extendedFamily, fms;
+	
+	fms = cpuid_eax (1);
+	baseFamily = extractbits (fms, 8, 11);
+	extendedFamily = extractbits (fms, 20, 27);
+	return baseFamily + extendedFamily;
+}
+
+
+// return non-zero for AMD family 0Fh processor found
+int is_family0Fh(void)
+{
+	return cpuidFamily() == 0x0F;
+}
+
+
+// return non-zero for AMD family 10h processor found
+int is_family10h(void)
+{
+	return cpuidFamily() == 0x10;
+}
Index: src/southbridge/amd/rs780/rs780_early_setup.c
===================================================================
--- src/southbridge/amd/rs780/rs780_early_setup.c	(revision 6011)
+++ src/southbridge/amd/rs780/rs780_early_setup.c	(working copy)
@@ -483,9 +483,11 @@ 
 	/* Reg94h[31:29] = 0x7 Enables HT transmitter de-emphasis */
 	set_nbcfg_enable_bits_8(nb_dev, 0x97, (u8)(~0x1F), 0xE0);
 
-	/*Reg8Ch[10:9] = 0x3 Enables Gfx Debug BAR,
-	 * force this BAR as mem type in rs780_gfx.c */
-	set_nbcfg_enable_bits_8(nb_dev, 0x8D, (u8)(~0xFF), 0x03);
+	/* Reg8Ch[9] enables Gfx Debug BAR programming
+	 * Reg8Ch[10] enables Gfx Debug BAR operation
+	 * Enable programming of the debug bar now, but enable
+	 * operation only after it has been programmed */
+	set_nbcfg_enable_bits_8(nb_dev, 0x8D, (u8)(~0xFF), 0x02);
 }
 
 static void rs780_por_mc_index_init(device_t nb_dev)
Index: src/southbridge/amd/rs780/rs780_gfx.c
===================================================================
--- src/southbridge/amd/rs780/rs780_gfx.c	(revision 6011)
+++ src/southbridge/amd/rs780/rs780_gfx.c	(working copy)
@@ -39,6 +39,8 @@ 
 void set_pcie_reset(void);
 void set_pcie_dereset(void);
 
+extern uint64_t uma_memory_base, uma_memory_size;
+
 /* Trust the original resource allocation. Don't do it again. */
 #undef DONT_TRUST_RESOURCE_ALLOCATION
 //#define DONT_TRUST_RESOURCE_ALLOCATION
@@ -304,11 +306,15 @@ 
 	volatile u32 * pointer;
 	int i;
 	u16 command;
-	u32 value, sblk;
+	u32 value;
 	u16 deviceid, vendorid;
 	device_t nb_dev = dev_find_slot(0, 0);
 	device_t k8_f2 = dev_find_slot(0, PCI_DEVFN(0x18, 2));
 	device_t k8_f0 = dev_find_slot(0, PCI_DEVFN(0x18, 0));
+	static u8 ht_freq_lookup [] = {2, 0, 4, 0, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 0, 0, 28, 30, 32};
+	static u8 ht_width_lookup [] = {8, 16, 0, 0, 2, 4, 0, 0};
+	static u16 memclk_lookup_fam0F [] = {100, 0, 133, 0, 0, 166, 0, 200};
+	static u16 memclk_lookup_fam10 [] = {200, 266, 333, 400, 533, 667, 800, 800};
 
 	/* We definetely will use this in future. Just leave it here. */
 	/*struct southbridge_amd_rs780_config *cfg =
@@ -339,6 +345,8 @@ 
 	*(GpuF0MMReg + 0x2180/4) = ((value&0xff00)>>8)|((value&0xff000000)>>8);
 	*(GpuF0MMReg + 0x2c04/4) = ((value&0xff00)<<8);
 	*(GpuF0MMReg + 0x5428/4) = ((value&0xffff0000)+0x10000)-((value&0xffff)<<16);
+	*(GpuF0MMReg + 0xF774/4) = 0xffffffff;
+	*(GpuF0MMReg + 0xF770/4) = 0x00000001;
 	*(GpuF0MMReg + 0x2000/4) = 0x00000011;
 	*(GpuF0MMReg + 0x200c/4) = 0x00000020;
 	*(GpuF0MMReg + 0x2010/4) = 0x10204810;
@@ -352,21 +360,26 @@ 
 	*(GpuF0MMReg + 0x7de4/4) |= (1<<3) | (1<<4);
 	/* Force allow LDT_STOP Cool'n'Quiet workaround. */
 	*(GpuF0MMReg + 0x655c/4) |= 1<<4;
+
+	// disable write combining, needed for stability
+	*(GpuF0MMReg + 0x2000/4) = 0x00000010;
+	*(GpuF0MMReg + 0x2408/4) = 1 << 9;
+	*(GpuF0MMReg + 0x2000/4) = 0x00000011;
+
 	/* GFX_InitFBAccess finished. */
 
+#if (CONFIG_GFXUMA == 1) /* for UMA mode. */
 	/* GFX_StartMC. */
-#if (CONFIG_GFXUMA == 1) /* for UMA mode. */
-	/* MC_INIT_COMPLETE. */
-	set_nbmc_enable_bits(nb_dev, 0x2, 0, 1<<31);
-	/* MC_STARTUP, MC_POWERED_UP and MC_VMODE.*/
-	set_nbmc_enable_bits(nb_dev, 0x1, 1<<18, 1|1<<2);
-
-	set_nbmc_enable_bits(nb_dev, 0xb1, 0, 1<<6);
-	set_nbmc_enable_bits(nb_dev, 0xc3, 0, 1);
-	nbmc_write_index(nb_dev, 0x07, 0x18);
-	nbmc_write_index(nb_dev, 0x06, 0x00000102);
-	nbmc_write_index(nb_dev, 0x09, 0x40000008);
-	set_nbmc_enable_bits(nb_dev, 0x6, 0, 1<<31);
+	set_nbmc_enable_bits(nb_dev, 0x02, 0x00000000, 0x80000000);
+	set_nbmc_enable_bits(nb_dev, 0x01, 0x00000000, 0x00000001);
+	set_nbmc_enable_bits(nb_dev, 0x01, 0x00000000, 0x00000004);
+	set_nbmc_enable_bits(nb_dev, 0x01, 0x00040000, 0x00000000);
+	set_nbmc_enable_bits(nb_dev, 0xB1, 0xFFFF0000, 0x00000040);
+	set_nbmc_enable_bits(nb_dev, 0xC3, 0x00000000, 0x00000001);
+	set_nbmc_enable_bits(nb_dev, 0x07, 0xFFFFFFFF, 0x00000018);
+	set_nbmc_enable_bits(nb_dev, 0x06, 0xFFFFFFFF, 0x00000102);
+	set_nbmc_enable_bits(nb_dev, 0x09, 0xFFFFFFFF, 0x40000008);
+	set_nbmc_enable_bits(nb_dev, 0x06, 0x00000000, 0x80000000);
 	/* GFX_StartMC finished. */
 #else
 	/* for SP mode. */
@@ -418,77 +431,110 @@ 
 	vgainfo.sHeader.ucTableContentRevision = 2;
 
 #if (CONFIG_GFXUMA == 0) /* SP mode. */
+	// Side port support is incomplete, do not use it
+	// These parameters must match the motherboard
 	vgainfo.ulBootUpSidePortClock = 667*100;
-	vgainfo.ucMemoryType = 3;
+	vgainfo.ucMemoryType = 3;  // 3=ddr3 sp mem, 2=ddr2 sp mem
 	vgainfo.ulMinSidePortClock = 333*100;
 #endif
 
-	vgainfo.ulBootUpEngineClock = 500 * 100; /* set boot up GFX engine clock. */
-	vgainfo.ulReserved1[0] = 0;	vgainfo.ulReserved1[1] = 0;
-	value = pci_read_config32(k8_f2, 0x94);
-	printk(BIOS_DEBUG, "MEMCLK = %x\n", value&0x7);
-	vgainfo.ulBootUpUMAClock = 333 * 100; /* set boot up UMA memory clock. */
-	vgainfo.ulBootUpSidePortClock = 0; /* disable SP. */
-	vgainfo.ulMinSidePortClock = 0; /* disable SP. */
-	for(i=0; i<6; i++)
-		vgainfo.ulReserved2[i] = 0;
-	vgainfo.ulSystemConfig = 0;
-	//vgainfo.ulSystemConfig |= 1<<1 | 1<<3 | 1<<4 | 1<<5 | 1<<6 | 1<<7 | 1;
-	vgainfo.ulBootUpReqDisplayVector = 0; //?
-	vgainfo.ulOtherDisplayMisc = 0; //?
-	vgainfo.ulDDISlot1Config = 0x000c0011; //0; //VGA
-	//vgainfo.ulDDISlot1Config = 0x000c00FF; //0; //HDMI
-	vgainfo.ulDDISlot2Config = 0x00130022; //0; //?
-	vgainfo.ucMemoryType = 2;
-	/* UMA Channel Number: 1 or 2. */
-	vgainfo.ucUMAChannelNumber = 2;
-	vgainfo.ucDockingPinBit = 0; //?
-	vgainfo.ucDockingPinPolarity = 0; //?
-	vgainfo.ulDockingPinCFGInfo = 0; //?
-	vgainfo.ulCPUCapInfo = 3; /* K8. */
+	vgainfo.ulBootUpEngineClock = 500 * 100;	       	// setup option on reference BIOS, 500 is default
 
-	/* page 5-19 on BDG. */
-	vgainfo.usNumberOfCyclesInPeriod = 0x8019;
-	vgainfo.usMaxNBVoltage = 0x1a;
-	vgainfo.usMinNBVoltage = 0;
-	vgainfo.usBootUpNBVoltage = 0x1a;
+	// find the DDR memory frequency
+	if (is_family10h()) {
+		value = pci_read_config32(k8_f2, 0x94);		// read channel 0 DRAM Configuration High Register
+		if (extractbit(value, 14))			// if channel 0 disabled, channel 1 must have memory
+			value = pci_read_config32(k8_f2, 0x194);// read channel 1 DRAM Configuration High Register
+		vgainfo.ulBootUpUMAClock = memclk_lookup_fam10 [extractbits (value, 0, 2)] * 100;
+	}
+	if (is_family0Fh()) {
+		value = pci_read_config32(k8_f2, 0x94);
+		vgainfo.ulBootUpUMAClock = memclk_lookup_fam0F [extractbits (value, 20, 22)] * 100;
+	}
 
-	/* Get SBLink value (HyperTransport I/O Hub Link ID). */
-	value = pci_read_config32(k8_f0, 0x64);
-	sblk = (value >> 8) & 0x3;
-	printk(BIOS_DEBUG, "SBLINK = %d.\n", sblk);
+	/* UMA Channel Number: 1 or 2. */
+	vgainfo.ucUMAChannelNumber = 1;
+	if (is_family0Fh()) {
+		value = pci_read_config32(k8_f2, 0x90);
+	if (extractbit(value, 11))  // 128-bit mode
+		vgainfo.ucUMAChannelNumber = 2;
+	}
+	if (is_family10h()) {
+		u32 dch0 = pci_read_config32(k8_f2, 0x94);
+		u32 dch1 = pci_read_config32(k8_f2, 0x194);
+		if (extractbit(dch0, 14) == 0 && extractbit(dch1, 14) == 0) { // both channels enabled
+			value = pci_read_config32(k8_f2, 0x110);
+			if (extractbit(value, 4))  // ganged mode
+			vgainfo.ucUMAChannelNumber = 2;
+		}
+	}
+      
+	// processor type
+	if (is_family0Fh())
+		vgainfo.ulCPUCapInfo = 3;
+	if (is_family10h())
+		vgainfo.ulCPUCapInfo = 2;
 
 	/* HT speed */
-	value = pci_read_config32(nb_dev, 0xd0);
-	printk(BIOS_DEBUG, "NB HT speed = %x.\n", value);
-	value = pci_read_config32(k8_f0, 0x88 + (sblk * 0x20));
-	printk(BIOS_DEBUG, "CPU HT speed = %x.\n", value);
-	vgainfo.ulHTLinkFreq = 100 * 100; /* set HT speed. */
+	value = pci_read_config8(nb_dev, 0xd1);
+	value = ht_freq_lookup [value] * 100;  // HT link frequency in MHz
+	vgainfo.ulHTLinkFreq = value * 100;    // HT frequency in units of 100 MHz
+	vgainfo.ulHighVoltageHTLinkFreq = vgainfo.ulHTLinkFreq;
+	vgainfo.ulLowVoltageHTLinkFreq = vgainfo.ulHTLinkFreq;
 
+	if (value <= 1800)
+		vgainfo.ulLowVoltageHTLinkFreq = vgainfo.ulHTLinkFreq;
+	else {
+		int sblink, cpuLnkFreqCap, nbLnkFreqCap;
+		value = pci_read_config32(k8_f0, 0x64);
+		sblink = extractbits(value, 8, 10);
+		cpuLnkFreqCap = pci_read_config16(k8_f0, 0x8a + sblink * 0x20);
+		nbLnkFreqCap = pci_read_config16(nb_dev, 0xd2);
+		if (cpuLnkFreqCap & nbLnkFreqCap & (1 << 10)) // if both 1800 MHz capable
+		vgainfo.ulLowVoltageHTLinkFreq = 1800*100;
+	}
+
 	/* HT width. */
-	value = pci_read_config32(nb_dev, 0xc8);
-	printk(BIOS_DEBUG, "HT width = %x.\n", value);
-	vgainfo.usMinHTLinkWidth = 16;
-	vgainfo.usMaxHTLinkWidth = 16;
-	vgainfo.usUMASyncStartDelay = 322;
-	vgainfo.usUMADataReturnTime = 86;
-	vgainfo.usLinkStatusZeroTime = 0x00c8; //0; //?
-	vgainfo.usReserved = 0;
-	vgainfo.ulHighVoltageHTLinkFreq = 100 * 100;
-	vgainfo.ulLowVoltageHTLinkFreq = 100 * 100;
-	vgainfo.usMaxUpStreamHTLinkWidth = 16;
-	vgainfo.usMaxDownStreamHTLinkWidth = 16;
-	vgainfo.usMinUpStreamHTLinkWidth = 16;
-	vgainfo.usMinDownStreamHTLinkWidth = 16;
-	for(i=0; i<97; i++)
-		vgainfo.ulReserved3[i] = 0;
+	value = pci_read_config8(nb_dev, 0xcb);
+	vgainfo.usMinDownStreamHTLinkWidth = 
+	vgainfo.usMaxDownStreamHTLinkWidth = 
+	vgainfo.usMinUpStreamHTLinkWidth = 
+	vgainfo.usMaxUpStreamHTLinkWidth =
+	vgainfo.usMinHTLinkWidth =
+	vgainfo.usMaxHTLinkWidth = ht_width_lookup [extractbits(value, 0, 2)];
 
+	if (is_family0Fh()) {
+		vgainfo.usUMASyncStartDelay = 322;
+		vgainfo.usUMADataReturnTime = 286;
+	}
+
+	if (is_family10h()) {
+		static u16 t0mult_lookup [] = {10, 50, 200, 2000};
+		int t0time, t0scale;
+		value = pci_read_config32(k8_f0, 0x16c);
+		t0time = extractbits(value, 0, 3);
+		t0scale = extractbits(value, 4, 5);
+		vgainfo.usLinkStatusZeroTime = t0mult_lookup [t0scale] * t0time;
+		vgainfo.usUMASyncStartDelay = 100;
+		if (vgainfo.ulHTLinkFreq < 1000 * 100) { // less than 1000 MHz
+			vgainfo.usUMADataReturnTime = 300;
+			vgainfo.usLinkStatusZeroTime = 6 * 100;   // 6us for GH in HT1 mode
+		}
+		else {
+			int lssel;
+			value = pci_read_config32(nb_dev, 0xac);
+			lssel = extractbits (value, 7, 8);
+			vgainfo.usUMADataReturnTime = 1300;
+			if (lssel == 0) vgainfo.usUMADataReturnTime = 150;
+		}
+	}
+
 	/* Transfer the Table to VBIOS. */
 	pointer = (u32 *)&vgainfo;
 	for(i=0; i<sizeof(ATOM_INTEGRATED_SYSTEM_INFO_V2); i+=4)
 	{
 #if (CONFIG_GFXUMA == 1)
-		*GpuF0MMReg = 0x80000000 + 0x10000000 - 512 + i;
+		*GpuF0MMReg = 0x80000000 + uma_memory_size - 512 + i;
 #else
 		*GpuF0MMReg = 0x80000000 + 0x8000000 - 512 + i;
 #endif
@@ -497,11 +543,22 @@ 
 
 	/* GFX_InitLate. */
 	{
-		u8 temp8;
-		temp8 = pci_read_config8(dev, 0x4);
-		//temp8 &= ~1; /* CIM clears this bit. Strangely, I can'd. */
-		temp8 |= 1<<1|1<<2;
-		pci_write_config8(dev, 0x4, temp8);
+		u32 temp;
+		temp = pci_read_config8(dev, 0x4);
+		//temp &= ~1; /* CIM clears this bit. Strangely, I can'd. */
+		temp |= 1<<1|1<<2;
+		pci_write_config8(dev, 0x4, temp);
+
+		// if the GFX debug bar is writable, then it has
+		// been programmed and can be safely enabled now
+		temp = pci_read_config32(nb_dev, 0x8c);
+
+		// if bits 1 (intgfx_enable) and 9 (gfx_debug_bar_enable)
+		// then enable gfx debug bar (set gxf_debug_decode_enable)
+		if (temp & 0x202)
+			temp |= (1 << 10);
+		pci_write_config32(nb_dev, 0x8c, temp);
+
 	}
 
 #ifdef DONT_TRUST_RESOURCE_ALLOCATION
@@ -584,7 +641,6 @@ 
 * Set registers in RS780 and CPU to enable the internal GFX.
 * Please refer to CIM source code and BKDG.
 */
-extern uint64_t uma_memory_base, uma_memory_size;
 
 static void rs780_internal_gfx_enable(device_t dev)
 {
@@ -637,7 +693,9 @@ 
 #if (CONFIG_GFXUMA == 1)
 	/* GFX_InitUMA. */
 	/* Copy CPU DDR Controller to NB MC. */
+	device_t k8_f1 = dev_find_slot(0, PCI_DEVFN(0x18, 1));
 	device_t k8_f2 = dev_find_slot(0, PCI_DEVFN(0x18, 2));
+	device_t k8_f4 = dev_find_slot(0, PCI_DEVFN(0x18, 4));
 	for (i = 0; i < 12; i++)
 	{
 		l_dword = pci_read_config32(k8_f2, 0x40 + i * 4);
@@ -646,24 +704,40 @@ 
 
 	l_dword = pci_read_config32(k8_f2, 0x80);
 	nbmc_write_index(nb_dev, 0x3c, l_dword);
-
 	l_dword = pci_read_config32(k8_f2, 0x94);
-	if(l_dword & (1<<22))
-		set_nbmc_enable_bits(nb_dev, 0x3c, 0, 1<<16);
-	else
-		set_nbmc_enable_bits(nb_dev, 0x3c, 1<<16, 0);
+	set_nbmc_enable_bits(nb_dev, 0x3c, 0, !!(l_dword & (1<<22))<<16);
+	set_nbmc_enable_bits(nb_dev, 0x3c, 0, !!(l_dword & (1<< 8))<<17);
+	l_dword = pci_read_config32(k8_f2, 0x90);
+	set_nbmc_enable_bits(nb_dev, 0x3c, 0, !!(l_dword & (1<<10))<<18);
+   if (is_family10h())
+   {
+	   for (i = 0; i < 12; i++)
+	   {
+		   l_dword = pci_read_config32(k8_f2, 0x140 + i * 4);
+		   nbmc_write_index(nb_dev, 0x3d + i, l_dword);
+	   }
 
-	if(l_dword & (1<<8))
-		set_nbmc_enable_bits(nb_dev, 0x3c, 0, 1<<17);
-	else
-		set_nbmc_enable_bits(nb_dev, 0x3c, 1<<17, 0);
+	   l_dword = pci_read_config32(k8_f2, 0x180);
+	   nbmc_write_index(nb_dev, 0x49, l_dword);
+	   l_dword = pci_read_config32(k8_f2, 0x194);
+	   set_nbmc_enable_bits(nb_dev, 0x49, 0, !!(l_dword & (1<<22))<<16);
+	   set_nbmc_enable_bits(nb_dev, 0x49, 0, !!(l_dword & (1<< 8))<<17);
+	   l_dword = pci_read_config32(k8_f2, 0x190);
+	   set_nbmc_enable_bits(nb_dev, 0x49, 0, !!(l_dword & (1<<10))<<18);
 
-	l_dword = pci_read_config32(k8_f2, 0x90);
-	if(l_dword & (1<<10))
-		set_nbmc_enable_bits(nb_dev, 0x3c, 0, 1<<18);
-	else
-		set_nbmc_enable_bits(nb_dev, 0x3c, 1<<18, 0);
+	   l_dword = pci_read_config32(k8_f2, 0x110);
+	   nbmc_write_index(nb_dev, 0x4a, l_dword);
+	   l_dword = pci_read_config32(k8_f2, 0x114);
+	   nbmc_write_index(nb_dev, 0x4b, l_dword);
+	   l_dword = pci_read_config32(k8_f4, 0x44);
+	   set_nbmc_enable_bits(nb_dev, 0x4a, 0, !!(l_dword & (1<<22))<<24);
+	   l_dword = pci_read_config32(k8_f1, 0x40);
+	   nbmc_write_index(nb_dev, 0x4c, l_dword);
+	   l_dword = pci_read_config32(k8_f1, 0xf0);
+	   nbmc_write_index(nb_dev, 0x4d, l_dword);
+   }
 
+
 	/* Set UMA in the 780 side. */
 	/* UMA start address, size. */
 	/* The UMA starts at 0xC0000000 of internal RS780 address space
@@ -672,7 +746,7 @@ 
 	nbmc_write_index(nb_dev, 0x10, ((uma_memory_size - 1 + 0xC0000000) & (~0xffff)) | 0xc000);
 	nbmc_write_index(nb_dev, 0x11, uma_memory_base);
 	nbmc_write_index(nb_dev, 0x12, 0);
-	nbmc_write_index(nb_dev, 0xf0, 256);
+	nbmc_write_index(nb_dev, 0xf0, uma_memory_size >> 20);
 	/* GFX_InitUMA finished. */
 #else
 	/* GFX_InitSP. */
@@ -1016,7 +1090,7 @@ 
 	/* 5.9.1.1. Disables the GFX REFCLK transmitter so that the GFX
 	 * REFCLK PAD can be driven by an external source. */
 	/* 5.9.1.2. Enables GFX REFCLK receiver to receive the REFCLK from an external source. */
-	set_nbmisc_enable_bits(nb_dev, 0x38, 1 << 29 | 1 << 28, 0 << 29 | 1 << 28);
+	set_nbmisc_enable_bits(nb_dev, 0x38, 1 << 29 | 1 << 28 | 1 << 26, 1 << 28);
 
 	/* 5.9.1.3 Selects the GFX REFCLK to be the source for PLL A. */
 	/* 5.9.1.4 Selects the GFX REFCLK to be the source for PLL B. */
Index: src/southbridge/amd/rs780/rs780_pcie.c
===================================================================
--- src/southbridge/amd/rs780/rs780_pcie.c	(revision 6011)
+++ src/southbridge/amd/rs780/rs780_pcie.c	(working copy)
@@ -221,6 +221,7 @@ 
 	printk(BIOS_DEBUG, "disable_pcie_bar3()\n");
 	pci_write_config32(nb_dev, 0x1C, 0);	/* clear BAR3 address */
 	set_nbcfg_enable_bits(nb_dev, 0x7C, 1 << 30, 0 << 30);	/* Disable writes to the BAR3. */
+	set_htiu_enable_bits(nb_dev, 0x32, 1 << 28, 0);	/* disable bar3 decode */
 	ProgK8TempMmioBase(0, EXT_CONF_BASE_ADDRESS, TEMP_MMIO_BASE_ADDRESS);
 }