/*
 * This file is part of the coreboot project.
 *
 *
 * 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_ops.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 = pcidev_on_root(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;
}
