From patchwork Wed Jan 30 03:59:23 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1033274 X-Patchwork-Delegate: bmeng.cn@gmail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=chromium.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="bCBSJNWr"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 43q9673HW7z9sBQ for ; Wed, 30 Jan 2019 15:16:15 +1100 (AEDT) Received: by lists.denx.de (Postfix, from userid 105) id 23832C21E0F; Wed, 30 Jan 2019 04:08:29 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=RCVD_IN_MSPIKE_H2, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id A9E43C21E85; Wed, 30 Jan 2019 04:02:40 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 5D3C1C21C4A; Wed, 30 Jan 2019 04:00:58 +0000 (UTC) Received: from mail-vs1-f72.google.com (mail-vs1-f72.google.com [209.85.217.72]) by lists.denx.de (Postfix) with ESMTPS id DECDFC21D8E for ; Wed, 30 Jan 2019 04:00:54 +0000 (UTC) Received: by mail-vs1-f72.google.com with SMTP id u29so10206271vsj.1 for ; Tue, 29 Jan 2019 20:00:54 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=L86I+SepNMlQvFvI424hz4VPspiHEw4vswPEkLJpf9U=; b=bCBSJNWrqjdr7F7Hw02TA2cn34l3pfrWg9P5sZYaVwd+fQq0z2vbBQZrO1oDE3O/xN gJgj98GqDIj2lz/fgxkDp5SkAR2GAqa54GgUs+wNONLZA/F46XFo3Z0hPd2VzUSki1rx YSAaEWiZCGVT9K8eA+8U+owYnlF3EGK1OKZmk= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=L86I+SepNMlQvFvI424hz4VPspiHEw4vswPEkLJpf9U=; b=Jjp7Hm/jY62sawluGplXDqEAGI0oykGc8xtMPiqaLxi45aEY2eLUWh3fR3b/C3GQJB yuVhu39NnTAOw8jhpjhUS7GXlVA/r2jBhnKU1//Z+p2cSwgHRPjvYyPsDu/fQffyME3O C2SAPTsRhdWr3PUKvtlKHktCEKVcB/afXJFAQWnHiuJwgjFskYG2bFVpP0nTMP2sMCYl vzl4K9/KqzZSyQt2IlZrrDu4JXNkyOL7jZZZO329120wT/GvrmNBehT7FCe43FslnnGk P2ZRcMoEkutnkHW8/+uKhxOWO0WqonoztcUyUJriCRKrwU3Bu10dUPMybnJ+hz5h39G6 0bDQ== X-Gm-Message-State: AHQUAuYdJfGFI5oa2FXa9mfcNvTw518DKVAffJMX1oNbePy6wpGV0Fae RIMuTeStMUNtQTt4t7v6Z9cmq8Jy0pMFb2kQ X-Google-Smtp-Source: AHgI3IZBzcNtvpbpmTgqsOg8mH7scnIErX86Se/QxNQvVQeKQrFypBhZn4yXiPUMNkYKhX7GE41JvGEzJ7C7Um4K X-Received: by 2002:a1f:ae14:: with SMTP id x20mr5911284vke.8.1548820853957; Tue, 29 Jan 2019 20:00:53 -0800 (PST) Date: Tue, 29 Jan 2019 20:59:23 -0700 In-Reply-To: <20190130035935.235565-1-sjg@chromium.org> Message-Id: <20190130035935.235565-29-sjg@chromium.org> Mime-Version: 1.0 References: <20190130035935.235565-1-sjg@chromium.org> X-Mailer: git-send-email 2.20.1.495.gaa96b0ce6b-goog From: Simon Glass To: U-Boot Mailing List Subject: [U-Boot] [PATCH 28/40] x86: Add a sysreset driver for the Intel PCH X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" Intel SoCs support a fairly stardard reset mechanism which can support powering off the device. Add support for this and enable it by default on broadwell, which already has the necessary pm.h header file. This driver augments the standard x86 sysreset driver. Signed-off-by: Simon Glass --- arch/x86/cpu/broadwell/Kconfig | 1 + drivers/sysreset/Kconfig | 9 ++ drivers/sysreset/Makefile | 1 + drivers/sysreset/sysreset_intel_pch.c | 125 ++++++++++++++++++++++++++ 4 files changed, 136 insertions(+) create mode 100644 drivers/sysreset/sysreset_intel_pch.c 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 + * + * Reset driver for intel x86 processors with a PCH. Supports powering the + * device off. + */ + +#include +#include +#include +#include +#include +#include +#include + +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, +};