i82801ix,bd82x6x,ibexpeak: rewrite expresscard hotplug

This implementation is more compact, unified and works with windows as well.

Tested under windows and under Debian GNU/Linux.

Change-Id: I585dec12e17e22d829baa3f2dc7aecc174f9d3b5
Signed-off-by: Vladimir Serbinenko <phcoder@gmail.com>
Reviewed-on: http://review.coreboot.org/7296
Reviewed-by: Edward O'Callaghan <eocallaghan@alterapraxis.com>
Reviewed-by: Nicolas Reinecke <nr@das-labor.org>
Tested-by: build bot (Jenkins)
diff --git a/src/southbridge/intel/i82801ix/Makefile.inc b/src/southbridge/intel/i82801ix/Makefile.inc
index 4117263..a6580c4 100644
--- a/src/southbridge/intel/i82801ix/Makefile.inc
+++ b/src/southbridge/intel/i82801ix/Makefile.inc
@@ -27,6 +27,7 @@
 ramstage-y += hdaudio.c
 ramstage-y += thermal.c
 ramstage-y += smbus.c
+ramstage-y += ../common/pciehp.c
 
 ramstage-srcs += src/mainboard/$(MAINBOARDDIR)/hda_verb.c
 
diff --git a/src/southbridge/intel/i82801ix/acpi/pcie.asl b/src/southbridge/intel/i82801ix/acpi/pcie.asl
index f02ad02..9233e5f 100644
--- a/src/southbridge/intel/i82801ix/acpi/pcie.asl
+++ b/src/southbridge/intel/i82801ix/acpi/pcie.asl
@@ -127,17 +127,6 @@
 		}
 
 	}
-
-#ifdef RP04_IS_EXPRESSCARD
-	Device (SLOT)
-	{
-		Name (_ADR, 0x00)
-		Method (_RMV, 0, NotSerialized)
-		{
-			Return (0x01)
-		}
-	}
-#endif
 }
 
 
diff --git a/src/southbridge/intel/i82801ix/chip.h b/src/southbridge/intel/i82801ix/chip.h
index 5e1221d..b8b58a6 100644
--- a/src/southbridge/intel/i82801ix/chip.h
+++ b/src/southbridge/intel/i82801ix/chip.h
@@ -88,6 +88,8 @@
 		uint8_t value : 8;
 		uint8_t scale : 2;
 	} pcie_power_limits[6];
+
+	uint8_t pcie_hotplug_map[8];
 };
 
 #endif				/* SOUTHBRIDGE_INTEL_I82801IX_CHIP_H */
diff --git a/src/southbridge/intel/i82801ix/lpc.c b/src/southbridge/intel/i82801ix/lpc.c
index dc2cfe8..e12c724 100644
--- a/src/southbridge/intel/i82801ix/lpc.c
+++ b/src/southbridge/intel/i82801ix/lpc.c
@@ -36,6 +36,7 @@
 #include <string.h>
 #include "i82801ix.h"
 #include "nvs.h"
+#include <southbridge/intel/common/pciehp.h>
 
 #define NMI_OFF	0
 
@@ -555,6 +556,14 @@
 		acpigen_pop_len();
 	}
 }
+
+static void southbridge_fill_ssdt(void)
+{
+	device_t dev = dev_find_slot(0, PCI_DEVFN(0x1f,0));
+	config_t *chip = dev->chip_info;
+
+	intel_acpi_pcie_hotplug_generator(chip->pcie_hotplug_map, 8);
+}
 #endif
 
 static struct pci_operations pci_ops = {
@@ -568,6 +577,7 @@
 #if IS_ENABLED(CONFIG_PER_DEVICE_ACPI_TABLES)
 	.acpi_inject_dsdt_generator = southbridge_inject_dsdt,
 	.write_acpi_tables      = acpi_write_hpet,
+	.acpi_fill_ssdt_generator = southbridge_fill_ssdt,
 #endif
 	.init			= lpc_init,
 	.scan_bus		= scan_static_bus,
diff --git a/src/southbridge/intel/i82801ix/pcie.c b/src/southbridge/intel/i82801ix/pcie.c
index 2022dac..7583715 100644
--- a/src/southbridge/intel/i82801ix/pcie.c
+++ b/src/southbridge/intel/i82801ix/pcie.c
@@ -24,11 +24,14 @@
 #include <device/pci.h>
 #include <device/pciexp.h>
 #include <device/pci_ids.h>
+#include <southbridge/intel/common/pciehp.h>
+#include "chip.h"
 
 static void pci_init(struct device *dev)
 {
 	u16 reg16;
 	u32 reg32;
+	struct southbridge_intel_i82801ix_config *config = dev->chip_info;
 
 	printk(BIOS_DEBUG, "Initializing ICH9 PCIe root port.\n");
 
@@ -85,6 +88,14 @@
 		reg32 |= (1 << 1);
 		pci_write_config32(dev, 0xe8, reg32);
 	}
+
+	/* Enable expresscard hotplug events.  */
+	if (config->pcie_hotplug_map[PCI_FUNC(dev->path.pci.devfn)]) {
+		pci_write_config32(dev, 0xd8,
+				   pci_read_config32(dev, 0xd8)
+				   | (1 << 30));
+		pci_write_config16(dev, 0x42, 0x142);
+	}
 }
 
 static void pcie_set_subsystem(device_t dev, unsigned vendor, unsigned device)
@@ -99,6 +110,21 @@
 	}
 }
 
+static unsigned int pch_pciexp_scan_bridge(device_t dev, unsigned int max)
+{
+	unsigned int ret;
+	struct southbridge_intel_i82801ix_config *config = dev->chip_info;
+
+	/* Normal PCIe Scan */
+	ret = pciexp_scan_bridge(dev, max);
+
+	if (config->pcie_hotplug_map[PCI_FUNC(dev->path.pci.devfn)]) {
+		intel_acpi_pcie_hotplug_scan_slot(dev->link_list);
+	}
+
+	return ret;
+}
+
 static struct pci_operations pci_ops = {
 	.set_subsystem = pcie_set_subsystem,
 };
@@ -108,7 +134,7 @@
 	.set_resources		= pci_dev_set_resources,
 	.enable_resources	= pci_bus_enable_resources,
 	.init			= pci_init,
-	.scan_bus		= pciexp_scan_bridge,
+	.scan_bus		= pch_pciexp_scan_bridge,
 	.ops_pci		= &pci_ops,
 };