fsp_broadwell_de: Add ability to set PCIe completion timeout

This enables the user to set the completion timeout value in PCI
Express Device Control 2 register via devicetree.cb.

Based on corebootBDE-270-iou-complto.patch in Arista EOS 4.20 release.

Change-Id: If0527899bc2047d0e57c11f7801768d07f9a5179
Signed-off-by: David Hendricks <dhendricks@fb.com>
Reviewed-on: https://review.coreboot.org/26225
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Werner Zeh <werner.zeh@siemens.com>
diff --git a/src/soc/intel/fsp_broadwell_de/Makefile.inc b/src/soc/intel/fsp_broadwell_de/Makefile.inc
index fc6cdd3..024035c 100644
--- a/src/soc/intel/fsp_broadwell_de/Makefile.inc
+++ b/src/soc/intel/fsp_broadwell_de/Makefile.inc
@@ -30,6 +30,7 @@
 romstage-y += tsc_freq.c
 ramstage-y += smi.c
 ramstage-y += gpio.c
+ramstage-y += iou_complto.c
 ramstage-$(CONFIG_HAVE_SMI_HANDLER) += smmrelocate.c
 ramstage-$(CONFIG_HAVE_SMI_HANDLER) += pmutil.c
 smm-$(CONFIG_HAVE_SMI_HANDLER) += pmutil.c
diff --git a/src/soc/intel/fsp_broadwell_de/chip.h b/src/soc/intel/fsp_broadwell_de/chip.h
index ed01c89..b7f59f7 100644
--- a/src/soc/intel/fsp_broadwell_de/chip.h
+++ b/src/soc/intel/fsp_broadwell_de/chip.h
@@ -23,7 +23,11 @@
  * specified by the devicetree. */
 
 struct soc_intel_fsp_broadwell_de_config {
+	/* PCIe completion timeout value */
+	int pcie_compltoval;
 };
 
+typedef struct soc_intel_fsp_broadwell_de_config config_t;
+
 extern struct chip_operations soc_intel_fsp_broadwell_de_ops;
 #endif /* _SOC_CHIP_H_ */
diff --git a/src/soc/intel/fsp_broadwell_de/iou_complto.c b/src/soc/intel/fsp_broadwell_de/iou_complto.c
new file mode 100644
index 0000000..dcc3071
--- /dev/null
+++ b/src/soc/intel/fsp_broadwell_de/iou_complto.c
@@ -0,0 +1,51 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015 Arista Networks, 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.
+ */
+
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include <soc/intel/fsp_broadwell_de/chip.h>
+
+#define DEVCTL2 0xb8
+
+static void iou_init(struct device *dev)
+{
+	const config_t *config = dev->chip_info;
+	u16 devctl2;
+
+	/* pcie completion timeout
+	   EDS Vol 2, Section 7.2.54 */
+	devctl2 = pci_read_config16(dev, DEVCTL2);
+	devctl2 = (devctl2 & ~0xf) | (config->pcie_compltoval & 0xf);
+	pci_write_config16(dev, DEVCTL2, devctl2);
+}
+
+static struct device_operations iou_ops = {
+	.read_resources   = pci_bus_read_resources,
+	.set_resources    = pci_dev_set_resources,
+	.enable_resources = pci_bus_enable_resources,
+	.scan_bus         = pci_scan_bridge,
+	.reset_bus        = pci_bus_reset,
+	.init             = iou_init,
+};
+
+static const unsigned short iou_device_ids[] = {
+	0x6f02, 0x6f08, 0 };
+
+static const struct pci_driver iou_driver __pci_driver = {
+	.ops    = &iou_ops,
+	.vendor = PCI_VENDOR_ID_INTEL,
+	.devices = iou_device_ids,
+};