* work is done in the northbridge(s).
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/agp_backend.h>
#include <linux/mmzone.h>
#include <asm/page.h> /* PAGE_SIZE */
-#include <asm/k8.h>
#include "agp.h"
+/* Will need to be increased if AMD64 ever goes >8-way. */
+#define MAX_HAMMER_GARTS 8
+
/* PTE bits. */
#define GPTE_VALID 1
#define GPTE_COHERENT 2
#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 = 1;
+#define for_each_nb() for(gart_iterator=0;gart_iterator<nr_garts;gart_iterator++)
+
+static void flush_amd64_tlb(struct pci_dev *dev)
+{
+ u32 tmp;
+
+ pci_read_config_dword (dev, AMD64_GARTCACHECTL, &tmp);
+ tmp |= INVGART;
+ pci_write_config_dword (dev, AMD64_GARTCACHECTL, tmp);
+}
+
static void amd64_tlbflush(struct agp_memory *temp)
{
- k8_flush_garts();
+ 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)
u32 temp;
struct aper_size_info_32 *values;
- dev = k8_northbridges[0];
+ dev = hammers[0];
if (dev==NULL)
return 0;
tmp &= ~(DISGARTCPU | DISGARTIO);
pci_write_config_dword(hammer, AMD64_GARTAPERTURECTL, tmp);
+ /* keep CPU's coherent. */
+ flush_amd64_tlb (hammer);
+
return aper_base;
}
static int amd_8151_configure(void)
{
unsigned long gatt_bus = virt_to_gart(agp_bridge->gatt_table_real);
- int i;
+ int gart_iterator;
/* Configure AGP regs in each x86-64 host bridge. */
- for (i = 0; i < num_k8_northbridges; i++) {
+ for_each_nb() {
agp_bridge->gart_bus_addr =
- amd64_configure(k8_northbridges[i], gatt_bus);
+ amd64_configure(hammers[gart_iterator],gatt_bus);
}
- k8_flush_garts();
return 0;
}
static void amd64_cleanup(void)
{
u32 tmp;
- int i;
- for (i = 0; i < num_k8_northbridges; i++) {
- struct pci_dev *dev = k8_northbridges[i];
+ int gart_iterator;
+ for_each_nb() {
/* disable gart translation */
- pci_read_config_dword (dev, AMD64_GARTAPERTURECTL, &tmp);
+ pci_read_config_dword (hammers[gart_iterator], AMD64_GARTAPERTURECTL, &tmp);
tmp &= ~AMD64_GARTEN;
- pci_write_config_dword (dev, AMD64_GARTAPERTURECTL, tmp);
+ pci_write_config_dword (hammers[gart_iterator], AMD64_GARTAPERTURECTL, tmp);
}
}
/*
* W*s centric BIOS sometimes only set up the aperture in the AGP
* bridge, not the northbridge. On AMD64 this is handled early
- * in aperture.c, but when IOMMU is not enabled or we run
+ * in aperture.c, but when GART_IOMMU is not enabled or we run
* on a 32bit kernel this needs to be redone.
* Unfortunately it is impossible to fix the aperture here because it's too late
* to allocate that much memory. But at least error out cleanly instead of
static __devinit int cache_nbs (struct pci_dev *pdev, u32 cap_ptr)
{
- int i;
-
- if (cache_k8_northbridges() < 0)
- return -ENODEV;
-
- i = 0;
- for (i = 0; i < num_k8_northbridges; i++) {
- struct pci_dev *dev = k8_northbridges[i];
- if (fix_northbridge(dev, pdev, cap_ptr) < 0) {
+ struct pci_dev *loop_dev = NULL;
+ int i = 0;
+
+ /* cache pci_devs of northbridges. */
+ 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");
+ return -1;
+ }
+ if (fix_northbridge(loop_dev, pdev, cap_ptr) < 0) {
printk(KERN_ERR PFX "No usable aperture found.\n");
#ifdef __x86_64__
/* should port this to i386 */
#endif
return -1;
}
+ hammers[i++] = loop_dev;
}
- return 0;
+ nr_garts = i;
+ return i == 0 ? -1 : 0;
}
/* Handle AMD 8151 quirks */
}
/* shadow x86-64 registers into ULi registers */
- pci_read_config_dword (k8_northbridges[0], AMD64_GARTAPERTUREBASE, &httfea);
+ pci_read_config_dword (hammers[0], AMD64_GARTAPERTUREBASE, &httfea);
/* if x86-64 aperture base is beyond 4G, exit here */
if ((httfea & 0x7fff) >> (32 - 25))
pci_write_config_dword(dev1, NVIDIA_X86_64_1_APSIZE, tmp);
/* shadow x86-64 registers into NVIDIA registers */
- pci_read_config_dword (k8_northbridges[0], AMD64_GARTAPERTUREBASE, &apbase);
+ pci_read_config_dword (hammers[0], AMD64_GARTAPERTUREBASE, &apbase);
/* if x86-64 aperture base is beyond 4G, exit here */
if ( (apbase & 0x7fff) >> (32 - 25) ) {
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_register_driver(&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_dev_present(k8_nb_ids))
+ if (!pci_dev_present(amd64nb))
return -ENODEV;
/* Look for any AGP bridge */
/* On AMD64 the PCI driver needs to initialize this driver early
for the IOMMU, so it has to be called via a backdoor. */
-#ifndef CONFIG_IOMMU
+#ifndef CONFIG_GART_IOMMU
module_init(agp_amd64_init);
module_exit(agp_amd64_cleanup);
#endif