/*
 * This file is part of the coreboot project.
 *
 * Copyright (C) 2007-2009 coresystems GmbH
 * Copyright (C) 2012 The Chromium OS Authors
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; version 2 of
 * the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#include <types.h>
#include <console/console.h>
#include <commonlib/helpers.h>
#include <arch/acpi.h>
#include <device/device.h>
#include <device/pci.h>
#include "sandybridge.h"
#include <southbridge/intel/bd82x6x/pch.h>

unsigned long acpi_fill_mcfg(unsigned long current)
{
	u32 pciexbar = 0;
	u32 pciexbar_reg;
	int max_buses;

	struct device *const dev = pcidev_on_root(0, 0);

	if (!dev)
		return current;

	pciexbar_reg=pci_read_config32(dev, PCIEXBAR);

	// MMCFG not supported or not enabled.
	if (!(pciexbar_reg & (1 << 0)))
		return current;

	switch ((pciexbar_reg >> 1) & 3) {
	case 0: // 256MB
		pciexbar = pciexbar_reg & ((1 << 31)|(1 << 30)|(1 << 29)|(1 << 28));
		max_buses = 256;
		break;
	case 1: // 128M
		pciexbar = pciexbar_reg & ((1 << 31)|(1 << 30)|(1 << 29)|(1 << 28)|(1 << 27));
		max_buses = 128;
		break;
	case 2: // 64M
		pciexbar = pciexbar_reg & ((1 << 31)|(1 << 30)|(1 << 29)|(1 << 28)|(1 << 27)|(1 << 26));
		max_buses = 64;
		break;
	default: // RSVD
		return current;
	}

	if (!pciexbar)
		return current;

	current += acpi_create_mcfg_mmconfig((acpi_mcfg_mmconfig_t *) current,
			pciexbar, 0x0, 0x0, max_buses - 1);

	return current;
}

static unsigned long acpi_create_igfx_rmrr(const unsigned long current)
{
	const u32 base_mask = ~(u32)(MiB - 1);

	struct device *const host = dev_find_slot(0, PCI_DEVFN(0, 0));
	if (!host)
		return 0;

	const u32 bgsm = pci_read_config32(host, BGSM) & base_mask;
	const u32 tolud = pci_read_config32(host, TOLUD) & base_mask;
	if (!bgsm || !tolud)
		return 0;

	return acpi_create_dmar_rmrr(current, 0, bgsm, tolud - 1);
}

static unsigned long acpi_fill_dmar(unsigned long current)
{
	const struct device *const igfx = pcidev_on_root(2, 0);

	if (igfx && igfx->enabled) {
		unsigned long tmp;

		tmp = current;
		current += acpi_create_dmar_drhd(current, 0, 0, IOMMU_BASE1);
		current += acpi_create_dmar_ds_pci(current, 0, 2, 0);
		current += acpi_create_dmar_ds_pci(current, 0, 2, 1);
		acpi_dmar_drhd_fixup(tmp, current);

		tmp = current;
		current += acpi_create_igfx_rmrr(current);
		if (current != tmp) {
			current += acpi_create_dmar_ds_pci(current, 0, 2, 0);
			current += acpi_create_dmar_ds_pci(current, 0, 2, 1);
			acpi_dmar_rmrr_fixup(tmp, current);
		}
	}

	const unsigned long tmp = current;
	current += acpi_create_dmar_drhd(current,
			DRHD_INCLUDE_PCI_ALL, 0, IOMMU_BASE2);
	current += acpi_create_dmar_ds_ioapic(current,
			2, PCH_IOAPIC_PCI_BUS, PCH_IOAPIC_PCI_SLOT, 0);
	size_t i;
	for (i = 0; i < 8; ++i)
		current += acpi_create_dmar_ds_msi_hpet(current,
				0, PCH_HPET_PCI_BUS, PCH_HPET_PCI_SLOT, i);
	acpi_dmar_drhd_fixup(tmp, current);

	return current;
}

unsigned long northbridge_write_acpi_tables(struct device *const dev,
					    unsigned long current,
					    struct acpi_rsdp *const rsdp)
{
	const u32 capid0_a = pci_read_config32(dev, 0xe4);
	if (capid0_a & (1 << 23))
		return current;

	printk(BIOS_DEBUG, "ACPI:     * DMAR\n");
	acpi_dmar_t *const dmar = (acpi_dmar_t *)current;
	acpi_create_dmar(dmar, DMAR_INTR_REMAP, acpi_fill_dmar);
	current += dmar->header.length;
	current = acpi_align_current(current);
	acpi_add_table(rsdp, dmar);

	current = acpi_align_current(current);

	printk(BIOS_DEBUG, "current = %lx\n", current);

	return current;
}
