diff --git a/arch/x86/cpu/broadwell/Kconfig b/arch/x86/cpu/broadwell/Kconfig
index 5b015c89d9..2955ffc55b 100644
--- a/arch/x86/cpu/broadwell/Kconfig
+++ b/arch/x86/cpu/broadwell/Kconfig
@@ -18,6 +18,7 @@ config INTEL_BROADWELL
 	imply USB
 	imply USB_EHCI_HCD
 	imply VIDEO_BROADWELL_IGD
+	imply SYSRESET_INTEL_PCH
 
 if INTEL_BROADWELL
 
diff --git a/drivers/sysreset/Kconfig b/drivers/sysreset/Kconfig
index 8ce3e2e207..f88412adcc 100644
--- a/drivers/sysreset/Kconfig
+++ b/drivers/sysreset/Kconfig
@@ -23,6 +23,15 @@ config SYSRESET_GPIO
 	  example on Microblaze where reset logic can be controlled via GPIO
 	  pin which triggers cpu reset.
 
+config SYSRESET_INTEL_PCH
+	bool "Enable support for Intel PCH reset driver"
+	depends on X86
+	help
+	  Enable this option to get reset support on Intel SoCs which have
+	  a common Platform-Controller Hub (PCH). This driver supports powering
+	  off the device. It augments the standard x86 sysreset driver which
+	  provides normal reset options.
+
 config SYSRESET_MICROBLAZE
 	bool "Enable support for Microblaze soft reset"
 	depends on MICROBLAZE
diff --git a/drivers/sysreset/Makefile b/drivers/sysreset/Makefile
index b3728ac17f..2add6cb37a 100644
--- a/drivers/sysreset/Makefile
+++ b/drivers/sysreset/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_ARCH_ROCKCHIP) += sysreset_rockchip.o
 obj-$(CONFIG_ARCH_STI) += sysreset_sti.o
 obj-$(CONFIG_SANDBOX) += sysreset_sandbox.o
 obj-$(CONFIG_SYSRESET_GPIO) += sysreset_gpio.o
+obj-$(CONFIG_SYSRESET_INTEL_PCH) += sysreset_intel_pch.o
 obj-$(CONFIG_SYSRESET_MCP83XX) += sysreset_mpc83xx.o
 obj-$(CONFIG_SYSRESET_MICROBLAZE) += sysreset_microblaze.o
 obj-$(CONFIG_SYSRESET_PSCI) += sysreset_psci.o
diff --git a/drivers/sysreset/sysreset_intel_pch.c b/drivers/sysreset/sysreset_intel_pch.c
new file mode 100644
index 0000000000..b60fa40dda
--- /dev/null
+++ b/drivers/sysreset/sysreset_intel_pch.c
@@ -0,0 +1,125 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Google Inc,
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * Reset driver for intel x86 processors with a PCH. Supports powering the
+ * device off.
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <sysreset.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/arch/pch.h>
+#include <asm/arch/pm.h>
+
+struct x86_reset_platdata {
+	struct udevice *pch;
+};
+
+/*
+ * Power down the machine by using the power management sleep control
+ * of the chipset. This will currently only work on Intel chipsets.
+ * However, adapting it to new chipsets is fairly simple. You will
+ * have to find the IO address of the power management register block
+ * in your southbridge, and look up the appropriate SLP_TYP_S5 value
+ * from your southbridge's data sheet.
+ *
+ * This function never returns.
+ */
+int pch_sysreset_power_off(struct udevice *dev)
+{
+	struct x86_reset_platdata *plat = dev_get_platdata(dev);
+	u16 pmbase;
+	u32 reg32;
+	int ret;
+
+	if (!plat->pch)
+		return -ENOENT;
+
+	/* Find the base address of the powermanagement registers */
+	ret = dm_pci_read_config16(plat->pch, 0x40, &pmbase);
+	if (ret)
+		return ret;
+
+	pmbase &= 0xfffe;
+
+	/* Mask interrupts or system might stay in a coma
+	 * (not executing code anymore, but not powered off either)
+	 */
+	asm("cli");
+
+	/*
+	 * Avoid any GPI waking the system from S5* or the system might stay in
+	 * a coma
+	 */
+	outl(0x00000000, pmbase + GPE0_EN(0));
+
+	/* Clear Power Button Status */
+	outw(PWRBTN_STS, pmbase + PM1_STS);
+
+	/* PMBASE + 4, Bit 10-12, Sleeping Type, * set to 111 -> S5, soft_off */
+	reg32 = inl(pmbase + PM1_CNT);
+
+	/* Set Sleeping Type to S5 (poweroff) */
+	reg32 &= ~(SLP_EN | SLP_TYP);
+	reg32 |= SLP_TYP_S5;
+	outl(reg32, pmbase + PM1_CNT);
+
+	/* Now set the Sleep Enable bit */
+	reg32 |= SLP_EN;
+	outl(reg32, pmbase + PM1_CNT);
+
+	for (;;)
+		asm("hlt");
+}
+
+static int pch_sysreset_request(struct udevice *dev, enum sysreset_t type)
+{
+	int ret;
+
+	switch (type) {
+	case SYSRESET_POWER_OFF:
+		ret = pch_sysreset_power_off(dev);
+		if (ret)
+			return ret;
+		break;
+	default:
+		return -ENOSYS;
+	}
+
+	return -EINPROGRESS;
+}
+
+static int pch_sysreset_ofdata_to_platdata(struct udevice *dev)
+{
+	struct x86_reset_platdata *plat = dev_get_platdata(dev);
+	int ret;
+
+	ret = uclass_get_device_by_phandle(UCLASS_PCH, dev, "intel,pch",
+					   &plat->pch);
+	if (ret && ret != -ENOENT)
+		return log_ret(ret);
+
+	return 0;
+}
+
+static const struct udevice_id pch_sysreset_ids[] = {
+	{ .compatible = "intel,pch-reset" },
+	{ }
+};
+
+static struct sysreset_ops pch_sysreset_ops = {
+	.request = pch_sysreset_request,
+};
+
+U_BOOT_DRIVER(pch_sysreset) = {
+	.name = "pch-sysreset",
+	.id = UCLASS_SYSRESET,
+	.of_match = pch_sysreset_ids,
+	.ops = &pch_sysreset_ops,
+	.flags = DM_FLAG_PRE_RELOC,
+	.ofdata_to_platdata	= pch_sysreset_ofdata_to_platdata,
+};
