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>
Acked-by: Rudolf Marek <r.marek@assembler.cz>

git-svn-id: svn://svn.coreboot.org/coreboot/trunk@6120 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
This commit is contained in:
Scott Duplichan 2010-11-24 00:39:44 +00:00
parent 0cda959710
commit 88dc531781
6 changed files with 255 additions and 112 deletions

View File

@ -133,11 +133,6 @@ static void rs780_nb_pci_table(device_t nb_dev)
temp32 = pci_read_config32(nb_dev, 0x4c); temp32 = pci_read_config32(nb_dev, 0x4c);
printk(BIOS_DEBUG, "NB_PCI_REG4C = %x.\n", temp32); 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. */ /* set temporary NB TOM to 0x40000000. */
rs780_set_tom(nb_dev); rs780_set_tom(nb_dev);
@ -194,14 +189,24 @@ static void rs780_nb_pci_table(device_t nb_dev)
static void rs780_nb_gfx_dev_table(device_t nb_dev, device_t dev) static void rs780_nb_gfx_dev_table(device_t nb_dev, device_t dev)
{ {
/* NB_InitGFXStraps */ /* NB_InitGFXStraps */
u32 MMIOBase, apc04, apc18, apc24; u32 MMIOBase, apc04, apc18, apc24, romstrap2;
msr_t pcie_mmio_save;
volatile u32 * strap; 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. */ /* Get PCIe configuration space. */
MMIOBase = pci_read_config32(nb_dev, 0x1c) & 0xfffffff0; MMIOBase = pci_read_config32(nb_dev, 0x1c) & 0xfffffff0;
/* Temporarily disable PCIe configuration space. */ /* Temporarily disable PCIe configuration space. */
set_htiu_enable_bits(nb_dev, 0x32, 1<<28, 0); 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_nbmisc_enable_bits(nb_dev, 0x1e, 0xffffffff, 1<<1 | 1<<4 | 1<<6 | 1<<7);
/* Set a temporary Bus number. */ /* Set a temporary Bus number. */
apc18 = pci_read_config32(dev, 0x18); apc18 = pci_read_config32(dev, 0x18);
@ -214,18 +219,27 @@ static void rs780_nb_gfx_dev_table(device_t nb_dev, device_t dev)
pci_write_config8(dev, 0x04, 0x02); pci_write_config8(dev, 0x04, 0x02);
/* Program Straps. */ /* Program Straps. */
strap = (volatile u32 *)(MMIOBase + 0x15020); romstrap2 = 1 << 26; // enables audio function
#if (CONFIG_GFXUMA == 1) #if (CONFIG_GFXUMA == 1)
*strap = 1<<7; /* the format of BIF_MEM_AP_SIZE. 001->256MB? */ extern uint64_t uma_memory_size;
#else // bits 7-9: aperture size
*strap = 0; /* 128M SP memory, 000 -> 128MB */ // 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 #endif
strap = (volatile u32 *)(MMIOBase + 0x15020);
*strap = romstrap2;
strap = (volatile u32 *)(MMIOBase + 0x15000); strap = (volatile u32 *)(MMIOBase + 0x15000);
*strap = 0x2c006300; *strap = 0x2c006300;
strap = (volatile u32 *)(MMIOBase + 0x15010); strap = (volatile u32 *)(MMIOBase + 0x15010);
*strap = 0x03015330; *strap = 0x03015330;
//strap = (volatile u32 *)(MMIOBase + 0x15020); strap = (volatile u32 *)(MMIOBase + 0x15020);
//*strap |= 0x00000040; /* Disable HDA device. */ *strap = romstrap2 | 0x00000040;
strap = (volatile u32 *)(MMIOBase + 0x15030); strap = (volatile u32 *)(MMIOBase + 0x15030);
*strap = 0x00001002; *strap = 0x00001002;
strap = (volatile u32 *)(MMIOBase + 0x15040); strap = (volatile u32 *)(MMIOBase + 0x15040);
@ -240,8 +254,9 @@ static void rs780_nb_gfx_dev_table(device_t nb_dev, device_t dev)
/* BIF switches into normal functional mode. */ /* BIF switches into normal functional mode. */
set_nbmisc_enable_bits(nb_dev, 0x1e, 1<<4 | 1<<5, 1<<5); set_nbmisc_enable_bits(nb_dev, 0x1e, 1<<4 | 1<<5, 1<<5);
/* NB Revision is A12. */ /* NB Revision is A12 or newer */
set_nbmisc_enable_bits(nb_dev, 0x1e, 1<<9, 1<<9); if (get_nb_rev(nb_dev) >= REV_RS780_A12)
set_nbmisc_enable_bits(nb_dev, 0x1e, 1<<9, 1<<9);
/* Restore APC04, APC18, APC24. */ /* Restore APC04, APC18, APC24. */
pci_write_config32(dev, 0x04, apc04); pci_write_config32(dev, 0x04, apc04);
@ -250,6 +265,11 @@ static void rs780_nb_gfx_dev_table(device_t nb_dev, device_t dev)
/* Enable PCIe configuration space. */ /* Enable PCIe configuration space. */
set_htiu_enable_bits(nb_dev, 0x32, 0, 1<<28); 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"); printk(BIOS_INFO, "GC is accessible from now on.\n");
} }
@ -332,18 +352,17 @@ void rs780_enable(device_t dev)
(dev->enabled ? 1 : 0) << 6); (dev->enabled ? 1 : 0) << 6);
if (dev->enabled) if (dev->enabled)
rs780_gpp_sb_init(nb_dev, dev, dev_ind); rs780_gpp_sb_init(nb_dev, dev, dev_ind);
disable_pcie_bar3(nb_dev);
break; break;
case 9: /* bus 0, dev 9,10, GPP */ case 9: /* bus 0, dev 9,10, GPP */
case 10: case 10:
printk(BIOS_INFO, "Bus-0, Dev-9, 10, Fun-0. enable=%d\n", printk(BIOS_INFO, "Bus-0, Dev-9, 10, Fun-0. enable=%d\n",
dev->enabled); dev->enabled);
enable_pcie_bar3(nb_dev); /* PCIEMiscInit */
set_nbmisc_enable_bits(nb_dev, 0x0c, 1 << (7 + dev_ind), set_nbmisc_enable_bits(nb_dev, 0x0c, 1 << (7 + dev_ind),
(dev->enabled ? 0 : 1) << (7 + dev_ind)); (dev->enabled ? 0 : 1) << (7 + dev_ind));
if (dev->enabled) if (dev->enabled)
rs780_gpp_sb_init(nb_dev, dev, dev_ind); 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; break;
default: default:
printk(BIOS_DEBUG, "unknown dev: %s\n", dev_path(dev)); printk(BIOS_DEBUG, "unknown dev: %s\n", dev_path(dev));

View File

@ -208,4 +208,9 @@ void avoid_lpc_dma_deadlock(device_t nb_dev, device_t sb_dev);
void config_gpp_core(device_t nb_dev, device_t sb_dev); void config_gpp_core(device_t nb_dev, device_t sb_dev);
void PcieReleasePortTraining(device_t nb_dev, device_t dev, u32 port); void PcieReleasePortTraining(device_t nb_dev, device_t dev, u32 port);
u8 PcieTrainPort(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 */ #endif /* RS780_H */

View File

@ -29,6 +29,7 @@
#include <cpu/amd/mtrr.h> #include <cpu/amd/mtrr.h>
#include <boot/coreboot_tables.h> #include <boot/coreboot_tables.h>
#include <delay.h> #include <delay.h>
#include <cpu/cpu.h>
#include "rs780.h" #include "rs780.h"
static u32 nb_read_index(device_t dev, u32 index_reg, u32 index) static u32 nb_read_index(device_t dev, u32 index_reg, u32 index)
@ -361,3 +362,42 @@ void rs780_set_tom(device_t nb_dev)
pci_write_config32(nb_dev, 0x90, uma_memory_base); pci_write_config32(nb_dev, 0x90, uma_memory_base);
//nbmc_write_index(nb_dev, 0x1e, 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;
}

View File

@ -483,9 +483,11 @@ static void rs780_por_pcicfg_init(device_t nb_dev)
/* Reg94h[31:29] = 0x7 Enables HT transmitter de-emphasis */ /* Reg94h[31:29] = 0x7 Enables HT transmitter de-emphasis */
set_nbcfg_enable_bits_8(nb_dev, 0x97, (u8)(~0x1F), 0xE0); set_nbcfg_enable_bits_8(nb_dev, 0x97, (u8)(~0x1F), 0xE0);
/*Reg8Ch[10:9] = 0x3 Enables Gfx Debug BAR, /* Reg8Ch[9] enables Gfx Debug BAR programming
* force this BAR as mem type in rs780_gfx.c */ * Reg8Ch[10] enables Gfx Debug BAR operation
set_nbcfg_enable_bits_8(nb_dev, 0x8D, (u8)(~0xFF), 0x03); * 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) static void rs780_por_mc_index_init(device_t nb_dev)

View File

@ -39,6 +39,8 @@ extern int is_dev3_present(void);
void set_pcie_reset(void); void set_pcie_reset(void);
void set_pcie_dereset(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. */ /* Trust the original resource allocation. Don't do it again. */
#undef DONT_TRUST_RESOURCE_ALLOCATION #undef DONT_TRUST_RESOURCE_ALLOCATION
//#define DONT_TRUST_RESOURCE_ALLOCATION //#define DONT_TRUST_RESOURCE_ALLOCATION
@ -304,11 +306,15 @@ static void internal_gfx_pci_dev_init(struct device *dev)
volatile u32 * pointer; volatile u32 * pointer;
int i; int i;
u16 command; u16 command;
u32 value, sblk; u32 value;
u16 deviceid, vendorid; u16 deviceid, vendorid;
device_t nb_dev = dev_find_slot(0, 0); device_t nb_dev = dev_find_slot(0, 0);
device_t k8_f2 = dev_find_slot(0, PCI_DEVFN(0x18, 2)); device_t k8_f2 = dev_find_slot(0, PCI_DEVFN(0x18, 2));
device_t k8_f0 = dev_find_slot(0, PCI_DEVFN(0x18, 0)); device_t k8_f0 = dev_find_slot(0, PCI_DEVFN(0x18, 0));
static const 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 const u8 ht_width_lookup [] = {8, 16, 0, 0, 2, 4, 0, 0};
static const u16 memclk_lookup_fam0F [] = {100, 0, 133, 0, 0, 166, 0, 200};
static const u16 memclk_lookup_fam10 [] = {200, 266, 333, 400, 533, 667, 800, 800};
/* We definetely will use this in future. Just leave it here. */ /* We definetely will use this in future. Just leave it here. */
/*struct southbridge_amd_rs780_config *cfg = /*struct southbridge_amd_rs780_config *cfg =
@ -339,6 +345,8 @@ static void internal_gfx_pci_dev_init(struct device *dev)
*(GpuF0MMReg + 0x2180/4) = ((value&0xff00)>>8)|((value&0xff000000)>>8); *(GpuF0MMReg + 0x2180/4) = ((value&0xff00)>>8)|((value&0xff000000)>>8);
*(GpuF0MMReg + 0x2c04/4) = ((value&0xff00)<<8); *(GpuF0MMReg + 0x2c04/4) = ((value&0xff00)<<8);
*(GpuF0MMReg + 0x5428/4) = ((value&0xffff0000)+0x10000)-((value&0xffff)<<16); *(GpuF0MMReg + 0x5428/4) = ((value&0xffff0000)+0x10000)-((value&0xffff)<<16);
*(GpuF0MMReg + 0xF774/4) = 0xffffffff;
*(GpuF0MMReg + 0xF770/4) = 0x00000001;
*(GpuF0MMReg + 0x2000/4) = 0x00000011; *(GpuF0MMReg + 0x2000/4) = 0x00000011;
*(GpuF0MMReg + 0x200c/4) = 0x00000020; *(GpuF0MMReg + 0x200c/4) = 0x00000020;
*(GpuF0MMReg + 0x2010/4) = 0x10204810; *(GpuF0MMReg + 0x2010/4) = 0x10204810;
@ -352,21 +360,28 @@ static void internal_gfx_pci_dev_init(struct device *dev)
*(GpuF0MMReg + 0x7de4/4) |= (1<<3) | (1<<4); *(GpuF0MMReg + 0x7de4/4) |= (1<<3) | (1<<4);
/* Force allow LDT_STOP Cool'n'Quiet workaround. */ /* Force allow LDT_STOP Cool'n'Quiet workaround. */
*(GpuF0MMReg + 0x655c/4) |= 1<<4; *(GpuF0MMReg + 0x655c/4) |= 1<<4;
// disable write combining, needed for stability
// reference bios does this only for RS780 rev A11
// need to figure out why we need it for all revs
*(GpuF0MMReg + 0x2000/4) = 0x00000010;
*(GpuF0MMReg + 0x2408/4) = 1 << 9;
*(GpuF0MMReg + 0x2000/4) = 0x00000011;
/* GFX_InitFBAccess finished. */ /* GFX_InitFBAccess finished. */
/* GFX_StartMC. */
#if (CONFIG_GFXUMA == 1) /* for UMA mode. */ #if (CONFIG_GFXUMA == 1) /* for UMA mode. */
/* MC_INIT_COMPLETE. */ /* GFX_StartMC. */
set_nbmc_enable_bits(nb_dev, 0x2, 0, 1<<31); set_nbmc_enable_bits(nb_dev, 0x02, 0x00000000, 0x80000000);
/* MC_STARTUP, MC_POWERED_UP and MC_VMODE.*/ set_nbmc_enable_bits(nb_dev, 0x01, 0x00000000, 0x00000001);
set_nbmc_enable_bits(nb_dev, 0x1, 1<<18, 1|1<<2); 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, 0, 1<<6); set_nbmc_enable_bits(nb_dev, 0xB1, 0xFFFF0000, 0x00000040);
set_nbmc_enable_bits(nb_dev, 0xc3, 0, 1); set_nbmc_enable_bits(nb_dev, 0xC3, 0x00000000, 0x00000001);
nbmc_write_index(nb_dev, 0x07, 0x18); set_nbmc_enable_bits(nb_dev, 0x07, 0xFFFFFFFF, 0x00000018);
nbmc_write_index(nb_dev, 0x06, 0x00000102); set_nbmc_enable_bits(nb_dev, 0x06, 0xFFFFFFFF, 0x00000102);
nbmc_write_index(nb_dev, 0x09, 0x40000008); set_nbmc_enable_bits(nb_dev, 0x09, 0xFFFFFFFF, 0x40000008);
set_nbmc_enable_bits(nb_dev, 0x6, 0, 1<<31); set_nbmc_enable_bits(nb_dev, 0x06, 0x00000000, 0x80000000);
/* GFX_StartMC finished. */ /* GFX_StartMC finished. */
#else #else
/* for SP mode. */ /* for SP mode. */
@ -418,77 +433,110 @@ static void internal_gfx_pci_dev_init(struct device *dev)
vgainfo.sHeader.ucTableContentRevision = 2; vgainfo.sHeader.ucTableContentRevision = 2;
#if (CONFIG_GFXUMA == 0) /* SP mode. */ #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.ulBootUpSidePortClock = 667*100;
vgainfo.ucMemoryType = 3; vgainfo.ucMemoryType = 3; // 3=ddr3 sp mem, 2=ddr2 sp mem
vgainfo.ulMinSidePortClock = 333*100; vgainfo.ulMinSidePortClock = 333*100;
#endif #endif
vgainfo.ulBootUpEngineClock = 500 * 100; /* set boot up GFX engine clock. */ vgainfo.ulBootUpEngineClock = 500 * 100; // setup option on reference BIOS, 500 is default
vgainfo.ulReserved1[0] = 0; vgainfo.ulReserved1[1] = 0;
value = pci_read_config32(k8_f2, 0x94); // find the DDR memory frequency
printk(BIOS_DEBUG, "MEMCLK = %x\n", value&0x7); if (is_family10h()) {
vgainfo.ulBootUpUMAClock = 333 * 100; /* set boot up UMA memory clock. */ value = pci_read_config32(k8_f2, 0x94); // read channel 0 DRAM Configuration High Register
vgainfo.ulBootUpSidePortClock = 0; /* disable SP. */ if (extractbit(value, 14)) // if channel 0 disabled, channel 1 must have memory
vgainfo.ulMinSidePortClock = 0; /* disable SP. */ value = pci_read_config32(k8_f2, 0x194);// read channel 1 DRAM Configuration High Register
for(i=0; i<6; i++) vgainfo.ulBootUpUMAClock = memclk_lookup_fam10 [extractbits (value, 0, 2)] * 100;
vgainfo.ulReserved2[i] = 0; }
vgainfo.ulSystemConfig = 0; if (is_family0Fh()) {
//vgainfo.ulSystemConfig |= 1<<1 | 1<<3 | 1<<4 | 1<<5 | 1<<6 | 1<<7 | 1; value = pci_read_config32(k8_f2, 0x94);
vgainfo.ulBootUpReqDisplayVector = 0; //? vgainfo.ulBootUpUMAClock = memclk_lookup_fam0F [extractbits (value, 20, 22)] * 100;
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. */ /* UMA Channel Number: 1 or 2. */
vgainfo.ucUMAChannelNumber = 2; vgainfo.ucUMAChannelNumber = 1;
vgainfo.ucDockingPinBit = 0; //? if (is_family0Fh()) {
vgainfo.ucDockingPinPolarity = 0; //? value = pci_read_config32(k8_f2, 0x90);
vgainfo.ulDockingPinCFGInfo = 0; //? if (extractbit(value, 11)) // 128-bit mode
vgainfo.ulCPUCapInfo = 3; /* K8. */ 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;
}
}
/* page 5-19 on BDG. */ // processor type
vgainfo.usNumberOfCyclesInPeriod = 0x8019; if (is_family0Fh())
vgainfo.usMaxNBVoltage = 0x1a; vgainfo.ulCPUCapInfo = 3;
vgainfo.usMinNBVoltage = 0; if (is_family10h())
vgainfo.usBootUpNBVoltage = 0x1a; vgainfo.ulCPUCapInfo = 2;
/* 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);
/* HT speed */ /* HT speed */
value = pci_read_config32(nb_dev, 0xd0); value = pci_read_config8(nb_dev, 0xd1);
printk(BIOS_DEBUG, "NB HT speed = %x.\n", value); value = ht_freq_lookup [value] * 100; // HT link frequency in MHz
value = pci_read_config32(k8_f0, 0x88 + (sblk * 0x20)); vgainfo.ulHTLinkFreq = value * 100; // HT frequency in units of 100 MHz
printk(BIOS_DEBUG, "CPU HT speed = %x.\n", value); vgainfo.ulHighVoltageHTLinkFreq = vgainfo.ulHTLinkFreq;
vgainfo.ulHTLinkFreq = 100 * 100; /* set HT speed. */ 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. */ /* HT width. */
value = pci_read_config32(nb_dev, 0xc8); value = pci_read_config8(nb_dev, 0xcb);
printk(BIOS_DEBUG, "HT width = %x.\n", value); vgainfo.usMinDownStreamHTLinkWidth =
vgainfo.usMinHTLinkWidth = 16; vgainfo.usMaxDownStreamHTLinkWidth =
vgainfo.usMaxHTLinkWidth = 16; vgainfo.usMinUpStreamHTLinkWidth =
vgainfo.usUMASyncStartDelay = 322; vgainfo.usMaxUpStreamHTLinkWidth =
vgainfo.usUMADataReturnTime = 86; vgainfo.usMinHTLinkWidth =
vgainfo.usLinkStatusZeroTime = 0x00c8; //0; //? vgainfo.usMaxHTLinkWidth = ht_width_lookup [extractbits(value, 0, 2)];
vgainfo.usReserved = 0;
vgainfo.ulHighVoltageHTLinkFreq = 100 * 100; if (is_family0Fh()) {
vgainfo.ulLowVoltageHTLinkFreq = 100 * 100; vgainfo.usUMASyncStartDelay = 322;
vgainfo.usMaxUpStreamHTLinkWidth = 16; vgainfo.usUMADataReturnTime = 286;
vgainfo.usMaxDownStreamHTLinkWidth = 16; }
vgainfo.usMinUpStreamHTLinkWidth = 16;
vgainfo.usMinDownStreamHTLinkWidth = 16; if (is_family10h()) {
for(i=0; i<97; i++) static u16 t0mult_lookup [] = {10, 50, 200, 2000};
vgainfo.ulReserved3[i] = 0; 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. */ /* Transfer the Table to VBIOS. */
pointer = (u32 *)&vgainfo; pointer = (u32 *)&vgainfo;
for(i=0; i<sizeof(ATOM_INTEGRATED_SYSTEM_INFO_V2); i+=4) for(i=0; i<sizeof(ATOM_INTEGRATED_SYSTEM_INFO_V2); i+=4)
{ {
#if (CONFIG_GFXUMA == 1) #if (CONFIG_GFXUMA == 1)
*GpuF0MMReg = 0x80000000 + 0x10000000 - 512 + i; *GpuF0MMReg = 0x80000000 + uma_memory_size - 512 + i;
#else #else
*GpuF0MMReg = 0x80000000 + 0x8000000 - 512 + i; *GpuF0MMReg = 0x80000000 + 0x8000000 - 512 + i;
#endif #endif
@ -497,11 +545,22 @@ static void internal_gfx_pci_dev_init(struct device *dev)
/* GFX_InitLate. */ /* GFX_InitLate. */
{ {
u8 temp8; u32 temp;
temp8 = pci_read_config8(dev, 0x4); temp = pci_read_config8(dev, 0x4);
//temp8 &= ~1; /* CIM clears this bit. Strangely, I can'd. */ //temp &= ~1; /* CIM clears this bit. Strangely, I can'd. */
temp8 |= 1<<1|1<<2; temp |= 1<<1|1<<2;
pci_write_config8(dev, 0x4, temp8); 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 #ifdef DONT_TRUST_RESOURCE_ALLOCATION
@ -584,7 +643,6 @@ static void internal_gfx_pci_dev_init(struct device *dev)
* Set registers in RS780 and CPU to enable the internal GFX. * Set registers in RS780 and CPU to enable the internal GFX.
* Please refer to CIM source code and BKDG. * 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) static void rs780_internal_gfx_enable(device_t dev)
{ {
@ -637,7 +695,9 @@ static void rs780_internal_gfx_enable(device_t dev)
#if (CONFIG_GFXUMA == 1) #if (CONFIG_GFXUMA == 1)
/* GFX_InitUMA. */ /* GFX_InitUMA. */
/* Copy CPU DDR Controller to NB MC. */ /* 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_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++) for (i = 0; i < 12; i++)
{ {
l_dword = pci_read_config32(k8_f2, 0x40 + i * 4); l_dword = pci_read_config32(k8_f2, 0x40 + i * 4);
@ -646,23 +706,39 @@ static void rs780_internal_gfx_enable(device_t dev)
l_dword = pci_read_config32(k8_f2, 0x80); l_dword = pci_read_config32(k8_f2, 0x80);
nbmc_write_index(nb_dev, 0x3c, l_dword); nbmc_write_index(nb_dev, 0x3c, l_dword);
l_dword = pci_read_config32(k8_f2, 0x94); l_dword = pci_read_config32(k8_f2, 0x94);
if(l_dword & (1<<22)) set_nbmc_enable_bits(nb_dev, 0x3c, 0, !!(l_dword & (1<<22))<<16);
set_nbmc_enable_bits(nb_dev, 0x3c, 0, 1<<16); set_nbmc_enable_bits(nb_dev, 0x3c, 0, !!(l_dword & (1<< 8))<<17);
else
set_nbmc_enable_bits(nb_dev, 0x3c, 1<<16, 0);
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, 0x90); l_dword = pci_read_config32(k8_f2, 0x90);
if(l_dword & (1<<10)) set_nbmc_enable_bits(nb_dev, 0x3c, 0, !!(l_dword & (1<<10))<<18);
set_nbmc_enable_bits(nb_dev, 0x3c, 0, 1<<18); if (is_family10h())
else {
set_nbmc_enable_bits(nb_dev, 0x3c, 1<<18, 0); 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);
}
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, 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. */ /* Set UMA in the 780 side. */
/* UMA start address, size. */ /* UMA start address, size. */
@ -672,7 +748,7 @@ static void rs780_internal_gfx_enable(device_t dev)
nbmc_write_index(nb_dev, 0x10, ((uma_memory_size - 1 + 0xC0000000) & (~0xffff)) | 0xc000); 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, 0x11, uma_memory_base);
nbmc_write_index(nb_dev, 0x12, 0); 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. */ /* GFX_InitUMA finished. */
#else #else
/* GFX_InitSP. */ /* GFX_InitSP. */
@ -1016,7 +1092,7 @@ void rs780_gfx_init(device_t nb_dev, device_t dev, u32 port)
/* 5.9.1.1. Disables the GFX REFCLK transmitter so that the GFX /* 5.9.1.1. Disables the GFX REFCLK transmitter so that the GFX
* REFCLK PAD can be driven by an external source. */ * 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. */ /* 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.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. */ /* 5.9.1.4 Selects the GFX REFCLK to be the source for PLL B. */

View File

@ -221,6 +221,7 @@ void disable_pcie_bar3(device_t nb_dev)
printk(BIOS_DEBUG, "disable_pcie_bar3()\n"); printk(BIOS_DEBUG, "disable_pcie_bar3()\n");
pci_write_config32(nb_dev, 0x1C, 0); /* clear BAR3 address */ 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_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); ProgK8TempMmioBase(0, EXT_CONF_BASE_ADDRESS, TEMP_MMIO_BASE_ADDRESS);
} }