#include <linux/pci.h>
#include <linux/init.h>
#include <linux/agp_backend.h>
+#include <linux/mmzone.h>
+#include <asm/page.h> /* PAGE_SIZE */
#include "agp.h"
/* Will need to be increased if AMD64 ever goes >8-way. */
#define NVIDIA_X86_64_1_APBASE2 0xd8
#define NVIDIA_X86_64_1_APLIMIT2 0xdc
+/* ULi K8 registers */
+#define ULI_X86_64_BASE_ADDR 0x10
+#define ULI_X86_64_HTT_FEA_REG 0x50
+#define ULI_X86_64_ENU_SCR_REG 0x54
+
static int nr_garts;
static struct pci_dev * hammers[MAX_HAMMER_GARTS];
static struct resource *aperture_resource;
-static int __initdata agp_try_unsupported;
+static int __initdata agp_try_unsupported = 1;
-static int gart_iterator;
#define for_each_nb() for(gart_iterator=0;gart_iterator<nr_garts;gart_iterator++)
static void flush_amd64_tlb(struct pci_dev *dev)
static void amd64_tlbflush(struct agp_memory *temp)
{
+ int gart_iterator;
for_each_nb()
flush_amd64_tlb(hammers[gart_iterator]);
}
static int amd64_insert_memory(struct agp_memory *mem, off_t pg_start, int type)
{
int i, j, num_entries;
- long tmp;
+ long long tmp;
u32 pte;
num_entries = agp_num_entries();
/* gatt table should be empty. */
while (j < (pg_start + mem->page_count)) {
- if (!PGE_EMPTY(agp_bridge, agp_bridge->gatt_table[j]))
+ if (!PGE_EMPTY(agp_bridge, readl(agp_bridge->gatt_table+j)))
return -EBUSY;
j++;
}
}
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
- tmp = agp_bridge->driver->mask_memory(mem->memory[i], mem->type);
+ tmp = agp_bridge->driver->mask_memory(agp_bridge,
+ mem->memory[i], mem->type);
BUG_ON(tmp & 0xffffff0000000ffcULL);
pte = (tmp & 0x000000ff00000000ULL) >> 28;
pte |=(tmp & 0x00000000fffff000ULL);
pte |= GPTE_VALID | GPTE_COHERENT;
- agp_bridge->gatt_table[j] = pte;
+ writel(pte, agp_bridge->gatt_table+j);
+ readl(agp_bridge->gatt_table+j); /* PCI Posting. */
}
amd64_tlbflush(mem);
return 0;
{256, 65536, 6, 0x00000700 }, /* 1 1 1 0 0 0 */
{128, 32768, 5, 0x00000720 }, /* 1 1 1 1 0 0 */
{64, 16384, 4, 0x00000730 }, /* 1 1 1 1 1 0 */
- {32, 8192, 3, 0x00000738 } /* 1 1 1 1 1 1 */
+ {32, 8192, 3, 0x00000738 } /* 1 1 1 1 1 1 */
};
static int amd_8151_configure(void)
{
- unsigned long gatt_bus = virt_to_phys(agp_bridge->gatt_table_real);
+ unsigned long gatt_bus = virt_to_gart(agp_bridge->gatt_table_real);
+ int gart_iterator;
/* Configure AGP regs in each x86-64 host bridge. */
for_each_nb() {
static void amd64_cleanup(void)
{
u32 tmp;
-
+ int gart_iterator;
for_each_nb() {
/* disable gart translation */
pci_read_config_dword (hammers[gart_iterator], AMD64_GARTAPERTURECTL, &tmp);
}
-struct agp_bridge_driver amd_8151_driver = {
+static struct agp_bridge_driver amd_8151_driver = {
.owner = THIS_MODULE,
.aperture_sizes = amd_8151_sizes,
.size_type = U32_APER_SIZE,
int i = 0;
/* cache pci_devs of northbridges. */
- while ((loop_dev = pci_find_device(PCI_VENDOR_ID_AMD, 0x1103, loop_dev))
+ while ((loop_dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x1103, loop_dev))
!= NULL) {
if (i == MAX_HAMMER_GARTS) {
printk(KERN_ERR PFX "Too many northbridges for AGP\n");
}
}
-static struct aper_size_info_32 nforce3_sizes[5] =
+
+static const struct aper_size_info_32 uli_sizes[7] =
+{
+ {256, 65536, 6, 10},
+ {128, 32768, 5, 9},
+ {64, 16384, 4, 8},
+ {32, 8192, 3, 7},
+ {16, 4096, 2, 6},
+ {8, 2048, 1, 4},
+ {4, 1024, 0, 3}
+};
+static int __devinit uli_agp_init(struct pci_dev *pdev)
+{
+ u32 httfea,baseaddr,enuscr;
+ struct pci_dev *dev1;
+ int i;
+ unsigned size = amd64_fetch_size();
+ printk(KERN_INFO "Setting up ULi AGP.\n");
+ dev1 = pci_find_slot ((unsigned int)pdev->bus->number,PCI_DEVFN(0,0));
+ if (dev1 == NULL) {
+ printk(KERN_INFO PFX "Detected a ULi chipset, "
+ "but could not fine the secondary device.\n");
+ return -ENODEV;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(uli_sizes); i++)
+ if (uli_sizes[i].size == size)
+ break;
+
+ if (i == ARRAY_SIZE(uli_sizes)) {
+ printk(KERN_INFO PFX "No ULi size found for %d\n", size);
+ return -ENODEV;
+ }
+
+ /* shadow x86-64 registers into ULi registers */
+ pci_read_config_dword (hammers[0], AMD64_GARTAPERTUREBASE, &httfea);
+
+ /* if x86-64 aperture base is beyond 4G, exit here */
+ if ((httfea & 0x7fff) >> (32 - 25))
+ return -ENODEV;
+
+ httfea = (httfea& 0x7fff) << 25;
+
+ pci_read_config_dword(pdev, ULI_X86_64_BASE_ADDR, &baseaddr);
+ baseaddr&= ~PCI_BASE_ADDRESS_MEM_MASK;
+ baseaddr|= httfea;
+ pci_write_config_dword(pdev, ULI_X86_64_BASE_ADDR, baseaddr);
+
+ enuscr= httfea+ (size * 1024 * 1024) - 1;
+ pci_write_config_dword(dev1, ULI_X86_64_HTT_FEA_REG, httfea);
+ pci_write_config_dword(dev1, ULI_X86_64_ENU_SCR_REG, enuscr);
+ return 0;
+}
+
+
+static const struct aper_size_info_32 nforce3_sizes[5] =
{
{512, 131072, 7, 0x00000000 },
{256, 65536, 6, 0x00000008 },
pci_read_config_dword (hammers[0], AMD64_GARTAPERTUREBASE, &apbase);
/* if x86-64 aperture base is beyond 4G, exit here */
- if ( (apbase & 0x7fff) >> (32 - 25) )
- return -ENODEV;
+ if ( (apbase & 0x7fff) >> (32 - 25) ) {
+ printk(KERN_INFO PFX "aperture base > 4G\n");
+ return -ENODEV;
+ }
apbase = (apbase & 0x7fff) << 25;
}
}
+ if (pdev->vendor == PCI_VENDOR_ID_AL) {
+ int ret = uli_agp_init(pdev);
+ if (ret) {
+ agp_put_bridge(bridge);
+ return ret;
+ }
+ }
+
pci_set_drvdata(pdev, bridge);
return agp_add_bridge(bridge);
}
{
struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
- release_mem_region(virt_to_phys(bridge->gatt_table_real),
+ release_mem_region(virt_to_gart(bridge->gatt_table_real),
amd64_aperture_sizes[bridge->aperture_size_idx].size);
agp_remove_bridge(bridge);
agp_put_bridge(bridge);
}
+#ifdef CONFIG_PM
+
+static int agp_amd64_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ pci_save_state(pdev);
+ pci_set_power_state(pdev, pci_choose_state(pdev, state));
+
+ return 0;
+}
+
+static int agp_amd64_resume(struct pci_dev *pdev)
+{
+ pci_set_power_state(pdev, PCI_D0);
+ pci_restore_state(pdev);
+
+ if (pdev->vendor == PCI_VENDOR_ID_NVIDIA)
+ nforce3_agp_init(pdev);
+
+ return amd_8151_configure();
+}
+
+#endif /* CONFIG_PM */
+
static struct pci_device_id agp_amd64_pci_table[] = {
{
.class = (PCI_CLASS_BRIDGE_HOST << 8),
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
},
+ /* ULi M1689 */
+ {
+ .class = (PCI_CLASS_BRIDGE_HOST << 8),
+ .class_mask = ~0,
+ .vendor = PCI_VENDOR_ID_AL,
+ .device = PCI_DEVICE_ID_AL_M1689,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ },
+ /* VIA K8T800Pro */
+ {
+ .class = (PCI_CLASS_BRIDGE_HOST << 8),
+ .class_mask = ~0,
+ .vendor = PCI_VENDOR_ID_VIA,
+ .device = PCI_DEVICE_ID_VIA_K8T800PRO_0,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ },
/* VIA K8T800 */
{
.class = (PCI_CLASS_BRIDGE_HOST << 8),
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
},
+ /* VIA K8T890 */
{
.class = (PCI_CLASS_BRIDGE_HOST << 8),
.class_mask = ~0,
.vendor = PCI_VENDOR_ID_VIA,
- .device = PCI_DEVICE_ID_VIA_8380_0,
+ .device = PCI_DEVICE_ID_VIA_3238_0,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ },
+ /* VIA K8T800/K8M800/K8N800 */
+ {
+ .class = (PCI_CLASS_BRIDGE_HOST << 8),
+ .class_mask = ~0,
+ .vendor = PCI_VENDOR_ID_VIA,
+ .device = PCI_DEVICE_ID_VIA_838X_1,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
},
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
},
+ /* SIS 760 */
+ {
+ .class = (PCI_CLASS_BRIDGE_HOST << 8),
+ .class_mask = ~0,
+ .vendor = PCI_VENDOR_ID_SI,
+ .device = PCI_DEVICE_ID_SI_760,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ },
+ /* ALI/ULI M1695 */
+ {
+ .class = (PCI_CLASS_BRIDGE_HOST << 8),
+ .class_mask = ~0,
+ .vendor = PCI_VENDOR_ID_AL,
+ .device = 0x1695,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ },
+
{ }
};
.id_table = agp_amd64_pci_table,
.probe = agp_amd64_probe,
.remove = agp_amd64_remove,
+#ifdef CONFIG_PM
+ .suspend = agp_amd64_suspend,
+ .resume = agp_amd64_resume,
+#endif
};
int __init agp_amd64_init(void)
{
int err = 0;
+ static struct pci_device_id amd64nb[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x1103) },
+ { },
+ };
+
if (agp_off)
return -EINVAL;
- if (pci_module_init(&agp_amd64_pci_driver) > 0) {
+ if (pci_register_driver(&agp_amd64_pci_driver) > 0) {
struct pci_dev *dev;
if (!agp_try_unsupported && !agp_try_unsupported_boot) {
printk(KERN_INFO PFX "No supported AGP bridge found.\n");
}
/* First check that we have at least one AMD64 NB */
- if (!pci_find_device(PCI_VENDOR_ID_AMD, 0x1103, NULL))
+ if (!pci_dev_present(amd64nb))
return -ENODEV;
/* Look for any AGP bridge */
dev = NULL;
err = -ENODEV;
- while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev))) {
+ for_each_pci_dev(dev) {
if (!pci_find_capability(dev, PCI_CAP_ID_AGP))
continue;
/* Only one bridge supported right now */
#endif
MODULE_AUTHOR("Dave Jones <davej@codemonkey.org.uk>, Andi Kleen");
-MODULE_PARM(agp_try_unsupported, "1i");
-MODULE_LICENSE("GPL and additional rights");
+module_param(agp_try_unsupported, bool, 0);
+MODULE_LICENSE("GPL");