[U-Boot] [PATCH v2 32/50] x86: sysreset: Implement power-off if available
Bin Meng
bmeng.cn at gmail.com
Wed May 1 14:50:15 UTC 2019
Hi Simon,
On Fri, Apr 26, 2019 at 12:00 PM Simon Glass <sjg at chromium.org> wrote:
>
> On modern x86 devices we can power the system off using the power-
> management features of the PCH. Add an implementation for this.
>
> Signed-off-by: Simon Glass <sjg at chromium.org>
> ---
>
> Changes in v2:
> - Add new patch to implement power-off if available
>
> drivers/sysreset/sysreset_x86.c | 82 +++++++++++++++++++++++++++++++++
> 1 file changed, 82 insertions(+)
>
> diff --git a/drivers/sysreset/sysreset_x86.c b/drivers/sysreset/sysreset_x86.c
> index d484ec5de49..bd759aa8bf4 100644
> --- a/drivers/sysreset/sysreset_x86.c
> +++ b/drivers/sysreset/sysreset_x86.c
> @@ -7,14 +7,80 @@
>
> #include <common.h>
> #include <dm.h>
> +#include <pch.h>
> #include <sysreset.h>
> #include <asm/io.h>
> #include <asm/processor.h>
> #include <efi_loader.h>
>
> +struct x86_sysreset_platdata {
> + struct udevice *pch;
> +};
> +
> +#define PWRBTN_STS (1 << 8)
> +
> +#define SLP_EN (1 << 13)
> +#define SLP_TYP (7 << 10)
> +#define SLP_TYP_S5 7
> +
There are macros from acpi_s3.h that can be used directly here.
> +/*
> + * 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_sysreset_platdata *plat = dev_get_platdata(dev);
> + struct pch_pmbase_info pm;
> + u32 reg32;
> + int ret;
> +
> + if (!plat->pch)
> + return -ENOENT;
> + ret = pch_ioctl(plat->pch, PCH_REQ_PMBASE_INFO, &pm, sizeof(pm));
> + if (ret)
> + return ret;
> +
> +
> + /* Mask interrupts or system might stay in a coma
nits: wrong multi-line comment format
> + * (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, pm.base + pm.gpio0_en_ofs);
> +
> + /* Clear Power Button Status */
> + outw(PWRBTN_STS, pm.base + pm.pm1_sts_ofs);
> +
> + /* PMBASE + 4, Bit 10-12, Sleeping Type, * set to 111 -> S5, soft_off */
> + reg32 = inl(pm.base + pm.pm1_cnt_ofs);
> +
> + /* Set Sleeping Type to S5 (poweroff) */
> + reg32 &= ~(SLP_EN | SLP_TYP);
> + reg32 |= SLP_TYP_S5;
> + outl(reg32, pm.base + pm.pm1_cnt_ofs);
> +
> + /* Now set the Sleep Enable bit */
> + reg32 |= SLP_EN;
> + outl(reg32, pm.base + pm.pm1_cnt_ofs);
> +
> + for (;;)
> + asm("hlt");
> +}
> +
> static int x86_sysreset_request(struct udevice *dev, enum sysreset_t type)
> {
> int value;
> + int ret;
>
> switch (type) {
> case SYSRESET_WARM:
> @@ -23,6 +89,11 @@ static int x86_sysreset_request(struct udevice *dev, enum sysreset_t type)
> case SYSRESET_COLD:
> value = SYS_RST | RST_CPU | FULL_RST;
> break;
> + case SYSRESET_POWER_OFF:
> + ret = pch_sysreset_power_off(dev);
> + if (ret)
> + return ret;
> + return -EINPROGRESS;
> default:
> return -ENOSYS;
> }
> @@ -57,6 +128,15 @@ void __efi_runtime EFIAPI efi_reset_system(
> }
> #endif
>
> +static int x86_sysreset_probe(struct udevice *dev)
> +{
> + struct x86_sysreset_platdata *plat = dev_get_platdata(dev);
> +
> + /* Locate the PCH if there is one. It isn't essential */
> + uclass_first_device(UCLASS_PCH, &plat->pch);
> +
> + return 0;
> +}
>
> static const struct udevice_id x86_sysreset_ids[] = {
> { .compatible = "x86,reset" },
> @@ -72,4 +152,6 @@ U_BOOT_DRIVER(x86_sysreset) = {
> .id = UCLASS_SYSRESET,
> .of_match = x86_sysreset_ids,
> .ops = &x86_sysreset_ops,
> + .probe = x86_sysreset_probe,
> + .platdata_auto_alloc_size = sizeof(struct x86_sysreset_platdata),
> };
> --
Other than above two,
Reviewed-by: Bin Meng <bmeng.cn at gmail.com>
Regards,
Bin
More information about the U-Boot
mailing list