/*
 * This file is part of the coreboot project.
 *
 * Copyright (C) 2008-2009 coresystems GmbH
 * Copyright (C) 2013 Google Inc.
 *
 * 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include <stdint.h>
#include <arch/io.h>
#include <arch/acpi.h>
#include <bootstate.h>
#include <cbmem.h>
#include <console/console.h>
#include <cpu/x86/smm.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <pc80/mc146818rtc.h>
#include <drivers/uart/uart8250reg.h>

#include <baytrail/iomap.h>
#include <baytrail/irq.h>
#include <baytrail/lpc.h>
#include <baytrail/nvs.h>
#include <baytrail/pci_devs.h>
#include <baytrail/pmc.h>
#include <baytrail/ramstage.h>
#include <baytrail/spi.h>
#include "chip.h"

static inline void
add_mmio_resource(device_t dev, int i, unsigned long addr, unsigned long size)
{
	mmio_resource(dev, i, addr >> 10, size >> 10);
}

static void sc_add_mmio_resources(device_t dev)
{
	add_mmio_resource(dev, 0xfeb, ABORT_BASE_ADDRESS, ABORT_BASE_SIZE);
	add_mmio_resource(dev, PBASE, PMC_BASE_ADDRESS, PMC_BASE_SIZE);
	add_mmio_resource(dev, IOBASE, IO_BASE_ADDRESS, IO_BASE_SIZE);
	add_mmio_resource(dev, IBASE, ILB_BASE_ADDRESS, ILB_BASE_SIZE);
	add_mmio_resource(dev, SBASE, SPI_BASE_ADDRESS, SPI_BASE_SIZE);
	add_mmio_resource(dev, MPBASE, MPHY_BASE_ADDRESS, MPHY_BASE_SIZE);
	add_mmio_resource(dev, PUBASE, PUNIT_BASE_ADDRESS, PUNIT_BASE_SIZE);
	add_mmio_resource(dev, RCBA, RCBA_BASE_ADDRESS, RCBA_BASE_SIZE);
}

/* Default IO range claimed by the LPC device. The upper bound is exclusive. */
#define LPC_DEFAULT_IO_RANGE_LOWER 0
#define LPC_DEFAULT_IO_RANGE_UPPER 0x1000

static inline int io_range_in_default(int base, int size)
{
	/* Does it start above the range? */
	if (base >= LPC_DEFAULT_IO_RANGE_UPPER)
		return 0;

	/* Is it entirely contained? */
	if (base >= LPC_DEFAULT_IO_RANGE_LOWER &&
	    (base + size) < LPC_DEFAULT_IO_RANGE_UPPER)
		return 1;

	/* This will return not in range for partial overlaps. */
	return 0;
}

/*
 * Note: this function assumes there is no overlap with the default LPC device's
 * claimed range: LPC_DEFAULT_IO_RANGE_LOWER -> LPC_DEFAULT_IO_RANGE_UPPER.
 */
static void sc_add_io_resource(device_t dev, int base, int size, int index)
{
	struct resource *res;

	if (io_range_in_default(base, size))
		return;

	res = new_resource(dev, index);
	res->base = base;
	res->size = size;
	res->flags = IORESOURCE_IO | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
}

static void sc_add_io_resources(device_t dev)
{
	struct resource *res;

	/* Add the default claimed IO range for the LPC device. */
	res = new_resource(dev, 0);
	res->base = LPC_DEFAULT_IO_RANGE_LOWER;
	res->size = LPC_DEFAULT_IO_RANGE_UPPER - LPC_DEFAULT_IO_RANGE_LOWER;
	res->flags = IORESOURCE_IO | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;

	/* GPIO */
	sc_add_io_resource(dev, GPIO_BASE_ADDRESS, 256, GBASE);

	/* ACPI */
	sc_add_io_resource(dev, ACPI_BASE_ADDRESS, 128, ABASE);
}

static void sc_read_resources(device_t dev)
{
	/* Get the normal PCI resources of this device. */
	pci_dev_read_resources(dev);

	/* Add non-standard MMIO resources. */
	sc_add_mmio_resources(dev);

	/* Add IO resources. */
	sc_add_io_resources(dev);
}

static void sc_rtc_init(void)
{
	uint32_t gen_pmcon1;
	int rtc_fail;
	struct chipset_power_state *ps = cbmem_find(CBMEM_ID_POWER_STATE);

	if (ps != NULL) {
		gen_pmcon1 = ps->gen_pmcon1;
	} else {
		gen_pmcon1 = read32((u32 *)(PMC_BASE_ADDRESS + GEN_PMCON1));
	}

	rtc_fail = !!(gen_pmcon1 & RPS);

	if (rtc_fail) {
		printk(BIOS_DEBUG, "RTC failure.\n");
	}

	cmos_init(rtc_fail);
}

/*
 * The UART hardware loses power while in suspend. Because of this the kernel
 * can hang because it doesn't re-initialize serial ports it is using for
 * consoles at resume time. The following function configures the UART
 * if the hardware is enabled though it may not be the correct baud rate
 * or configuration.  This is definitely a hack, but it helps the kernel
 * along.
 */
static void com1_configure_resume(device_t dev)
{
	const uint16_t port = 0x3f8;

	/* Is the UART I/O port enabled? */
	if (!(pci_read_config32(dev, UART_CONT) & 1))
		return;

	/* Disable interrupts */
	outb(0x0, port + UART8250_IER);

	/* Enable FIFOs */
	outb(UART8250_FCR_FIFO_EN, port + UART8250_FCR);

	/* assert DTR and RTS so the other end is happy */
	outb(UART8250_MCR_DTR | UART8250_MCR_RTS, port + UART8250_MCR);

	/* DLAB on */
	outb(UART8250_LCR_DLAB | 3, port + UART8250_LCR);

	/* Set Baud Rate Divisor. 1 ==> 115200 Baud */
	outb(1, port + UART8250_DLL);
	outb(0, port + UART8250_DLM);

	/* Set to 3 for 8N1 */
	outb(3, port + UART8250_LCR);
}

static void sc_init(device_t dev)
{
	int i;
	u8 *pr_base = (u8 *)(ILB_BASE_ADDRESS + 0x08);
	u16 *ir_base = (u16 *)ILB_BASE_ADDRESS + 0x20;
	u32 *gen_pmcon1 = (u32 *)(PMC_BASE_ADDRESS + GEN_PMCON1);
	u32 *actl = (u32 *)(ILB_BASE_ADDRESS + ACTL);
	const struct baytrail_irq_route *ir = &global_baytrail_irq_route;
	struct soc_intel_baytrail_config *config = dev->chip_info;

	/* Set up the PIRQ PIC routing based on static config. */
	for (i = 0; i < NUM_PIRQS; i++) {
		write8(pr_base + i, ir->pic[i]);
	}
	/* Set up the per device PIRQ routing base on static config. */
	for (i = 0; i < NUM_IR_DEVS; i++) {
		write16(ir_base + i, ir->pcidev[i]);
	}

	/* Route SCI to IRQ9 */
	write32(actl, (read32(actl) & ~SCIS_MASK) | SCIS_IRQ9);

	sc_rtc_init();

	if (config->disable_slp_x_stretch_sus_fail) {
		printk(BIOS_DEBUG, "Disabling slp_x stretching.\n");
		write32(gen_pmcon1,
			read32(gen_pmcon1) | DIS_SLP_X_STRCH_SUS_UP);
	} else {
		write32(gen_pmcon1,
			read32(gen_pmcon1) & ~DIS_SLP_X_STRCH_SUS_UP);
	}

	if (acpi_is_wakeup_s3())
		com1_configure_resume(dev);
}

/*
 * Common code for the south cluster devices.
 */

/* Set bit in function disable register to hide this device. */
static void sc_disable_devfn(device_t dev)
{
	u32 *func_dis = (u32 *)(PMC_BASE_ADDRESS + FUNC_DIS);
	u32 *func_dis2 = (u32 *)(PMC_BASE_ADDRESS + FUNC_DIS2);
	uint32_t mask = 0;
	uint32_t mask2 = 0;

	switch (dev->path.pci.devfn) {
	case PCI_DEVFN(SDIO_DEV, SDIO_FUNC):
		mask |= SDIO_DIS;
		break;
	case PCI_DEVFN(SD_DEV, SD_FUNC):
		mask |= SD_DIS;
		break;
	case PCI_DEVFN(SATA_DEV, SATA_FUNC):
		mask |= SATA_DIS;
		break;
	case PCI_DEVFN(XHCI_DEV, XHCI_FUNC):
		mask |= XHCI_DIS;
		/* Disable super speed PHY when XHCI is not available. */
		mask2 |= USH_SS_PHY_DIS;
		break;
	case PCI_DEVFN(LPE_DEV, LPE_FUNC):
		mask |= LPE_DIS;
		break;
	case PCI_DEVFN(MMC_DEV, MMC_FUNC):
		mask |= MMC_DIS;
		break;
	case PCI_DEVFN(SIO_DMA1_DEV, SIO_DMA1_FUNC):
		mask |= SIO_DMA1_DIS;
		break;
	case PCI_DEVFN(I2C1_DEV, I2C1_FUNC):
		mask |= I2C1_DIS;
		break;
	case PCI_DEVFN(I2C2_DEV, I2C2_FUNC):
		mask |= I2C1_DIS;
		break;
	case PCI_DEVFN(I2C3_DEV, I2C3_FUNC):
		mask |= I2C3_DIS;
		break;
	case PCI_DEVFN(I2C4_DEV, I2C4_FUNC):
		mask |= I2C4_DIS;
		break;
	case PCI_DEVFN(I2C5_DEV, I2C5_FUNC):
		mask |= I2C5_DIS;
		break;
	case PCI_DEVFN(I2C6_DEV, I2C6_FUNC):
		mask |= I2C6_DIS;
		break;
	case PCI_DEVFN(I2C7_DEV, I2C7_FUNC):
		mask |= I2C7_DIS;
		break;
	case PCI_DEVFN(TXE_DEV, TXE_FUNC):
		mask |= TXE_DIS;
		break;
	case PCI_DEVFN(HDA_DEV, HDA_FUNC):
		mask |= HDA_DIS;
		break;
	case PCI_DEVFN(PCIE_PORT1_DEV, PCIE_PORT1_FUNC):
		mask |= PCIE_PORT1_DIS;
		break;
	case PCI_DEVFN(PCIE_PORT2_DEV, PCIE_PORT2_FUNC):
		mask |= PCIE_PORT2_DIS;
		break;
	case PCI_DEVFN(PCIE_PORT3_DEV, PCIE_PORT3_FUNC):
		mask |= PCIE_PORT3_DIS;
		break;
	case PCI_DEVFN(PCIE_PORT4_DEV, PCIE_PORT4_FUNC):
		mask |= PCIE_PORT4_DIS;
		break;
	case PCI_DEVFN(EHCI_DEV, EHCI_FUNC):
		mask |= EHCI_DIS;
		break;
	case PCI_DEVFN(SIO_DMA2_DEV, SIO_DMA2_FUNC):
		mask |= SIO_DMA2_DIS;
		break;
	case PCI_DEVFN(PWM1_DEV, PWM1_FUNC):
		mask |= PWM1_DIS;
		break;
	case PCI_DEVFN(PWM2_DEV, PWM2_FUNC):
		mask |= PWM2_DIS;
		break;
	case PCI_DEVFN(HSUART1_DEV, HSUART1_FUNC):
		mask |= HSUART1_DIS;
		break;
	case PCI_DEVFN(HSUART2_DEV, HSUART2_FUNC):
		mask |= HSUART2_DIS;
		break;
	case PCI_DEVFN(SPI_DEV, SPI_FUNC):
		mask |= SPI_DIS;
		break;
	case PCI_DEVFN(SMBUS_DEV, SMBUS_FUNC):
		mask2 |= SMBUS_DIS;
		break;
	}

	if (mask != 0) {
		write32(func_dis, read32(func_dis) | mask);
		/* Ensure posted write hits. */
		read32(func_dis);
	}

	if (mask2 != 0) {
		write32(func_dis2, read32(func_dis2) | mask2);
		/* Ensure posted write hits. */
		read32(func_dis2);
	}
}

static inline void set_d3hot_bits(device_t dev, int offset)
{
	uint32_t reg8;
	printk(BIOS_DEBUG, "Power management CAP offset 0x%x.\n", offset);
	reg8 = pci_read_config8(dev, offset + 4);
	reg8 |= 0x3;
	pci_write_config8(dev, offset + 4, reg8);
}

/* Parts of the audio subsystem are powered by the HDA device. Therefore, one
 * cannot put HDA into D3Hot. Instead perform this workaround to make some of
 * the audio paths work for LPE audio. */
static void hda_work_around(device_t dev)
{
	u32 *gctl = (u32 *)(TEMP_BASE_ADDRESS + 0x8);

	/* Need to set magic register 0x43 to 0xd7 in config space. */
	pci_write_config8(dev, 0x43, 0xd7);

	/* Need to set bit 0 of GCTL to take the device out of reset. However,
	 * that requires setting up the 64-bit BAR. */
	pci_write_config32(dev, PCI_BASE_ADDRESS_0, TEMP_BASE_ADDRESS);
	pci_write_config32(dev, PCI_BASE_ADDRESS_1, 0);
	pci_write_config8(dev, PCI_COMMAND, PCI_COMMAND_MEMORY);
	write32(gctl, read32(gctl) | 0x1);
	pci_write_config8(dev, PCI_COMMAND, 0);
	pci_write_config32(dev, PCI_BASE_ADDRESS_0, 0);
}

static int place_device_in_d3hot(device_t dev)
{
	unsigned offset;

	/* Parts of the HDA block are used for LPE audio as well.
	 * Therefore assume the HDA will never be put into D3Hot. */
	if (dev->path.pci.devfn == PCI_DEVFN(HDA_DEV, HDA_FUNC)) {
		hda_work_around(dev);
		return 0;
	}

	offset = pci_find_capability(dev, PCI_CAP_ID_PM);

	if (offset != 0) {
		set_d3hot_bits(dev, offset);
		return 0;
	}

	/* For some reason some of the devices don't have the capability
	 * pointer set correctly. Work around this by hard coding the offset. */
	switch (dev->path.pci.devfn) {
	case PCI_DEVFN(SDIO_DEV, SDIO_FUNC):
		offset = 0x80;
		break;
	case PCI_DEVFN(SD_DEV, SD_FUNC):
		offset = 0x80;
		break;
	case PCI_DEVFN(MMC_DEV, MMC_FUNC):
		offset = 0x80;
		break;
	case PCI_DEVFN(LPE_DEV, LPE_FUNC):
		offset = 0x80;
		break;
	case PCI_DEVFN(SIO_DMA1_DEV, SIO_DMA1_FUNC):
		offset = 0x80;
		break;
	case PCI_DEVFN(I2C1_DEV, I2C1_FUNC):
		offset = 0x80;
		break;
	case PCI_DEVFN(I2C2_DEV, I2C2_FUNC):
		offset = 0x80;
		break;
	case PCI_DEVFN(I2C3_DEV, I2C3_FUNC):
		offset = 0x80;
		break;
	case PCI_DEVFN(I2C4_DEV, I2C4_FUNC):
		offset = 0x80;
		break;
	case PCI_DEVFN(I2C5_DEV, I2C5_FUNC):
		offset = 0x80;
		break;
	case PCI_DEVFN(I2C6_DEV, I2C6_FUNC):
		offset = 0x80;
		break;
	case PCI_DEVFN(I2C7_DEV, I2C7_FUNC):
		offset = 0x80;
		break;
	case PCI_DEVFN(SIO_DMA2_DEV, SIO_DMA2_FUNC):
		offset = 0x80;
		break;
	case PCI_DEVFN(PWM1_DEV, PWM1_FUNC):
		offset = 0x80;
		break;
	case PCI_DEVFN(PWM2_DEV, PWM2_FUNC):
		offset = 0x80;
		break;
	case PCI_DEVFN(HSUART1_DEV, HSUART1_FUNC):
		offset = 0x80;
		break;
	case PCI_DEVFN(HSUART2_DEV, HSUART2_FUNC):
		offset = 0x80;
		break;
	case PCI_DEVFN(SPI_DEV, SPI_FUNC):
		offset = 0x80;
		break;
	case PCI_DEVFN(SATA_DEV, SATA_FUNC):
		offset = 0x70;
		break;
	case PCI_DEVFN(XHCI_DEV, XHCI_FUNC):
		offset = 0x70;
		break;
	case PCI_DEVFN(EHCI_DEV, EHCI_FUNC):
		offset = 0x70;
		break;
	case PCI_DEVFN(HDA_DEV, HDA_FUNC):
		offset = 0x50;
		break;
	case PCI_DEVFN(SMBUS_DEV, SMBUS_FUNC):
		offset = 0x50;
		break;
	case PCI_DEVFN(TXE_DEV, TXE_FUNC):
		/* TXE cannot be placed in D3Hot. */
		return 0;
	case PCI_DEVFN(PCIE_PORT1_DEV, PCIE_PORT1_FUNC):
		offset = 0xa0;
		break;
	case PCI_DEVFN(PCIE_PORT2_DEV, PCIE_PORT2_FUNC):
		offset = 0xa0;
		break;
	case PCI_DEVFN(PCIE_PORT3_DEV, PCIE_PORT3_FUNC):
		offset = 0xa0;
		break;
	case PCI_DEVFN(PCIE_PORT4_DEV, PCIE_PORT4_FUNC):
		offset = 0xa0;
		break;
	}

	if (offset != 0) {
		set_d3hot_bits(dev, offset);
		return 0;
	}

	return -1;
}

/* Common PCI device function disable. */
void southcluster_enable_dev(device_t dev)
{
	uint32_t reg32;

	if (!dev->enabled) {
		int slot = PCI_SLOT(dev->path.pci.devfn);
		int func = PCI_FUNC(dev->path.pci.devfn);
		printk(BIOS_DEBUG, "%s: Disabling device: %02x.%01x\n",
		       dev_path(dev), slot, func);

		/* Ensure memory, io, and bus master are all disabled */
		reg32 = pci_read_config32(dev, PCI_COMMAND);
		reg32 &= ~(PCI_COMMAND_MASTER |
			   PCI_COMMAND_MEMORY | PCI_COMMAND_IO);
		pci_write_config32(dev, PCI_COMMAND, reg32);

		/* Place device in D3Hot */
		if (place_device_in_d3hot(dev) < 0) {
			printk(BIOS_WARNING,
			       "Could not place %02x.%01x into D3Hot. "
			       "Keeping device visible.\n", slot, func);
			return;
		}
		/* Disable this device if possible */
		sc_disable_devfn(dev);
	} else {
		/* Enable SERR */
		reg32 = pci_read_config32(dev, PCI_COMMAND);
		reg32 |= PCI_COMMAND_SERR;
		pci_write_config32(dev, PCI_COMMAND, reg32);
	}
}

static struct device_operations device_ops = {
	.read_resources		= sc_read_resources,
	.set_resources		= pci_dev_set_resources,
	.enable_resources	= NULL,
	.init			= sc_init,
	.enable			= southcluster_enable_dev,
	.scan_bus		= scan_static_bus,
	.ops_pci		= &soc_pci_ops,
};

static const struct pci_driver southcluster __pci_driver = {
	.ops		= &device_ops,
	.vendor		= PCI_VENDOR_ID_INTEL,
	.device		= LPC_DEVID,
};

int __attribute__((weak)) mainboard_get_spi_config(struct spi_config *cfg)
{
	return -1;
}

static void finalize_chipset(void *unused)
{
	u32 *bcr = (u32 *)(SPI_BASE_ADDRESS + BCR);
	u32 *gcs = (u32 *)(RCBA_BASE_ADDRESS + GCS);
	u32 *gen_pmcon2 = (u32 *)(PMC_BASE_ADDRESS + GEN_PMCON2);
	u32 *etr = (u32 *)(PMC_BASE_ADDRESS + ETR);
	u8 *spi = (u8 *)SPI_BASE_ADDRESS;
	struct spi_config cfg;

	/* Set the lock enable on the BIOS control register. */
	write32(bcr, read32(bcr) | BCR_LE);

	/* Set BIOS lock down bit controlling boot block size and swapping. */
	write32(gcs, read32(gcs) | BILD);

	/* Lock sleep stretching policy and set SMI lock. */
	write32(gen_pmcon2, read32(gen_pmcon2) | SLPSX_STR_POL_LOCK | SMI_LOCK);

	/*  Set the CF9 lock. */
	write32(etr, read32(etr) | CF9LOCK);

	if (mainboard_get_spi_config(&cfg) < 0) {
		printk(BIOS_DEBUG, "No SPI lockdown configuration.\n");
	} else {
		write16(spi + PREOP, cfg.preop);
		write16(spi + OPTYPE, cfg.optype);
		write32(spi + OPMENU0, cfg.opmenu[0]);
		write32(spi + OPMENU1, cfg.opmenu[1]);
		write16(spi + HSFSTS, read16(spi + HSFSTS) | FLOCKDN);
		write32(spi + UVSCC, cfg.uvscc);
		write32(spi + LVSCC, cfg.lvscc | VCL);
	}

	printk(BIOS_DEBUG, "Finalizing SMM.\n");
	outb(APM_CNT_FINALIZE, APM_CNT);
}

BOOT_STATE_INIT_ENTRY(BS_OS_RESUME, BS_ON_ENTRY, finalize_chipset, NULL);
BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_LOAD, BS_ON_EXIT, finalize_chipset, NULL);
