Commit 06477bc3 authored by Dave Jones's avatar Dave Jones Committed by Dave Jones

[AGPGART] Merge missing chunk of NVIDIA nForce agpgart driver.

This bit has been in the 2.4 driver since it appeared, but I dropped
it (partly deliberatly), and then forgot all about it.
Turns out that some systems really need this stuff, as their BIOS hasn't
set up the IORRs.

http://bugme.osdl.org/show_bug.cgi?id=1521
parent 5fde0e6e
......@@ -46,10 +46,54 @@ static int nvidia_fetch_size(void)
return 0;
}
#define SYSCFG 0xC0010010
#define IORR_BASE0 0xC0010016
#define IORR_MASK0 0xC0010017
#define AMD_K7_NUM_IORR 2
static int nvidia_init_iorr(u32 base, u32 size)
{
u32 base_hi, base_lo;
u32 mask_hi, mask_lo;
u32 sys_hi, sys_lo;
u32 iorr_addr, free_iorr_addr;
/* Find the iorr that is already used for the base */
/* If not found, determine the uppermost available iorr */
free_iorr_addr = AMD_K7_NUM_IORR;
for(iorr_addr = 0; iorr_addr < AMD_K7_NUM_IORR; iorr_addr++) {
rdmsr(IORR_BASE0 + 2 * iorr_addr, base_lo, base_hi);
rdmsr(IORR_MASK0 + 2 * iorr_addr, mask_lo, mask_hi);
if ((base_lo & 0xfffff000) == (base & 0xfffff000))
break;
if ((mask_lo & 0x00000800) == 0)
free_iorr_addr = iorr_addr;
}
if (iorr_addr >= AMD_K7_NUM_IORR) {
iorr_addr = free_iorr_addr;
if (iorr_addr >= AMD_K7_NUM_IORR)
return -EINVAL;
}
base_hi = 0x0;
base_lo = (base & ~0xfff) | 0x18;
mask_hi = 0xf;
mask_lo = ((~(size - 1)) & 0xfffff000) | 0x800;
wrmsr(IORR_BASE0 + 2 * iorr_addr, base_lo, base_hi);
wrmsr(IORR_MASK0 + 2 * iorr_addr, mask_lo, mask_hi);
rdmsr(SYSCFG, sys_lo, sys_hi);
sys_lo |= 0x00100000;
wrmsr(SYSCFG, sys_lo, sys_hi);
return 0;
}
static int nvidia_configure(void)
{
int i, num_dirs;
int i, rc, num_dirs;
u32 apbase, aplimit;
struct aper_size_info_8 *current_size;
u32 temp;
......@@ -69,6 +113,8 @@ static int nvidia_configure(void)
pci_write_config_dword(nvidia_private.dev_2, NVIDIA_2_APLIMIT, aplimit);
pci_write_config_dword(nvidia_private.dev_3, NVIDIA_3_APBASE, apbase);
pci_write_config_dword(nvidia_private.dev_3, NVIDIA_3_APLIMIT, aplimit);
if (0 != (rc = nvidia_init_iorr(apbase, current_size->size * 1024 * 1024)))
return rc;
/* directory size is 64k */
num_dirs = current_size->size / 64;
......@@ -122,6 +168,10 @@ static void nvidia_cleanup(void)
previous_size = A_SIZE_8(agp_bridge->previous_size);
pci_write_config_byte(agp_bridge->dev, NVIDIA_0_APSIZE,
previous_size->size_value);
/* restore iorr for previous aperture size */
nvidia_init_iorr(agp_bridge->gart_bus_addr,
previous_size->size * 1024 * 1024);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment