/*
 * Shared support code for AMD K8 northbridges and derivates.
 * Copyright 2006 Andi Kleen, SUSE Labs. Subject to GPLv2.
 */
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/module.h>
#include <linux/spinlock.h>
#include <asm/k8.h>

int num_k8_northbridges;
EXPORT_SYMBOL(num_k8_northbridges);

static u32 *flush_words;

struct pci_device_id k8_nb_ids[] = {
	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_MISC) },
	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_MISC) },
	{}
};
EXPORT_SYMBOL(k8_nb_ids);

struct pci_dev **k8_northbridges;
EXPORT_SYMBOL(k8_northbridges);

static struct pci_dev *next_k8_northbridge(struct pci_dev *dev)
{
	do {
		dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev);
		if (!dev)
			break;
	} while (!pci_match_id(&k8_nb_ids[0], dev));
	return dev;
}

int cache_k8_northbridges(void)
{
	int i;
	struct pci_dev *dev;

	if (num_k8_northbridges)
		return 0;

	dev = NULL;
	while ((dev = next_k8_northbridge(dev)) != NULL)
		num_k8_northbridges++;

	k8_northbridges = kmalloc((num_k8_northbridges + 1) * sizeof(void *),
				  GFP_KERNEL);
	if (!k8_northbridges)
		return -ENOMEM;

	if (!num_k8_northbridges) {
		k8_northbridges[0] = NULL;
		return 0;
	}

	flush_words = kmalloc(num_k8_northbridges * sizeof(u32), GFP_KERNEL);
	if (!flush_words) {
		kfree(k8_northbridges);
		return -ENOMEM;
	}

	dev = NULL;
	i = 0;
	while ((dev = next_k8_northbridge(dev)) != NULL) {
		k8_northbridges[i] = dev;
		pci_read_config_dword(dev, 0x9c, &flush_words[i++]);
	}
	k8_northbridges[i] = NULL;
	return 0;
}
EXPORT_SYMBOL_GPL(cache_k8_northbridges);

/* Ignores subdevice/subvendor but as far as I can figure out
   they're useless anyways */
int __init early_is_k8_nb(u32 device)
{
	struct pci_device_id *id;
	u32 vendor = device & 0xffff;
	device >>= 16;
	for (id = k8_nb_ids; id->vendor; id++)
		if (vendor == id->vendor && device == id->device)
			return 1;
	return 0;
}

void k8_flush_garts(void)
{
	int flushed, i;
	unsigned long flags;
	static DEFINE_SPINLOCK(gart_lock);

	/* Avoid races between AGP and IOMMU. In theory it's not needed
	   but I'm not sure if the hardware won't lose flush requests
	   when another is pending. This whole thing is so expensive anyways
	   that it doesn't matter to serialize more. -AK */
	spin_lock_irqsave(&gart_lock, flags);
	flushed = 0;
	for (i = 0; i < num_k8_northbridges; i++) {
		pci_write_config_dword(k8_northbridges[i], 0x9c,
				       flush_words[i]|1);
		flushed++;
	}
	for (i = 0; i < num_k8_northbridges; i++) {
		u32 w;
		/* Make sure the hardware actually executed the flush*/
		for (;;) {
			pci_read_config_dword(k8_northbridges[i],
					      0x9c, &w);
			if (!(w & 1))
				break;
			cpu_relax();
		}
	}
	spin_unlock_irqrestore(&gart_lock, flags);
	if (!flushed)
		printk("nothing to flush?\n");
}
EXPORT_SYMBOL_GPL(k8_flush_garts);

static __init int init_k8_nbs(void)
{
	int err = 0;

	err = cache_k8_northbridges();

	if (err < 0)
		printk(KERN_NOTICE "K8 NB: Cannot enumerate AMD northbridges.\n");

	return err;
}

/* This has to go after the PCI subsystem */
fs_initcall(init_k8_nbs);
