aboutsummaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorAymeric Wibo <obiwac@FreeBSD.org>2025-06-14 15:33:24 +0000
committerAymeric Wibo <obiwac@FreeBSD.org>2026-03-04 15:38:57 +0000
commit2c60fce365f4398ff02a86b46e2862905f88fa97 (patch)
treee0343187b77ff75f9151519a4500b5038c8f9cbf /sys/dev
parent40e52e0edd038460a2a2aca017b3ac5a513fe37b (diff)
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/amdsmu/amdsmu.c48
-rw-r--r--sys/dev/amdsmu/amdsmu.h11
-rw-r--r--sys/dev/amdsmu/amdsmu_reg.h1
3 files changed, 57 insertions, 3 deletions
diff --git a/sys/dev/amdsmu/amdsmu.c b/sys/dev/amdsmu/amdsmu.c
index 416f875c6176..9a6873b43517 100644
--- a/sys/dev/amdsmu/amdsmu.c
+++ b/sys/dev/amdsmu/amdsmu.c
@@ -1,7 +1,7 @@
/*
* SPDX-License-Identifier: BSD-2-Clause
*
- * Copyright (c) 2025 The FreeBSD Foundation
+ * Copyright (c) 2025-2026 The FreeBSD Foundation
*
* This software was developed by Aymeric Wibo <obiwac@freebsd.org>
* under sponsorship from the FreeBSD Foundation.
@@ -14,6 +14,13 @@
#include <sys/rman.h>
#include <sys/sysctl.h>
+#include "opt_acpi.h"
+
+#if defined(DEV_ACPI)
+#include <contrib/dev/acpica/include/acpi.h>
+#include <dev/acpica/acpivar.h>
+#endif
+
#include <dev/pci/pcivar.h>
#include <dev/amdsmu/amdsmu.h>
@@ -289,6 +296,27 @@ amdsmu_fetch_idlemask(device_t dev)
sc->idlemask = amdsmu_read4(sc, SMU_REG_IDLEMASK);
}
+static void
+amdsmu_suspend(device_t dev, enum power_stype stype)
+{
+ if (stype != POWER_STYPE_SUSPEND_TO_IDLE)
+ return;
+ if (amdsmu_cmd(dev, SMU_MSG_SLEEP_HINT, true, NULL) != 0)
+ device_printf(dev, "failed to hint to SMU to enter sleep");
+}
+
+static void
+amdsmu_resume(device_t dev, enum power_stype stype)
+{
+ if (stype != POWER_STYPE_SUSPEND_TO_IDLE)
+ return;
+ if (amdsmu_cmd(dev, SMU_MSG_SLEEP_HINT, false, NULL) != 0)
+ device_printf(dev, "failed to hint to SMU to exit sleep");
+ /* Update metrics after resume. */
+ amdsmu_dump_metrics(dev);
+ amdsmu_fetch_idlemask(dev);
+}
+
static int
amdsmu_attach(device_t dev)
{
@@ -422,6 +450,19 @@ amdsmu_attach(device_t dev)
"value is not documented - only used to help AMD internally debug "
"issues");
+#if defined(DEV_ACPI)
+ /*
+ * Register post device suspend/pre device resume eventhandlers. We use
+ * a lower priority for the suspend event as we want this to be called
+ * after the SPMC suspend hook, and a higher priority for the resume
+ * event as we want this to be called before the SPMC hook.
+ */
+ sc->eh_suspend = EVENTHANDLER_REGISTER(acpi_post_dev_suspend,
+ amdsmu_suspend, dev, -10);
+ sc->eh_resume = EVENTHANDLER_REGISTER(acpi_pre_dev_resume,
+ amdsmu_resume, dev, 10);
+#endif
+
return (0);
err_dump:
bus_space_unmap(sc->bus_tag, sc->reg_space, SMU_MEM_SIZE);
@@ -438,6 +479,11 @@ amdsmu_detach(device_t dev)
struct amdsmu_softc *sc = device_get_softc(dev);
int rid = 0;
+#if defined(DEV_ACPI)
+ EVENTHANDLER_DEREGISTER(acpi_post_dev_suspend, sc->eh_suspend);
+ EVENTHANDLER_DEREGISTER(acpi_pre_dev_resume, sc->eh_resume);
+#endif
+
bus_space_unmap(sc->bus_tag, sc->smu_space, SMU_MEM_SIZE);
bus_space_unmap(sc->bus_tag, sc->reg_space, SMU_MEM_SIZE);
diff --git a/sys/dev/amdsmu/amdsmu.h b/sys/dev/amdsmu/amdsmu.h
index 025887f7fe5a..857fa21cba4e 100644
--- a/sys/dev/amdsmu/amdsmu.h
+++ b/sys/dev/amdsmu/amdsmu.h
@@ -6,11 +6,13 @@
* This software was developed by Aymeric Wibo <obiwac@freebsd.org>
* under sponsorship from the FreeBSD Foundation.
*/
+
#ifndef _AMDSMU_H_
#define _AMDSMU_H_
#include <sys/param.h>
#include <sys/bus.h>
+#include <sys/eventhandler.h>
#include <sys/kernel.h>
#include <machine/bus.h>
#include <x86/cputypes.h>
@@ -60,6 +62,9 @@ struct amdsmu_softc {
struct sysctl_ctx_list *sysctlctx;
struct sysctl_oid *sysctlnode;
+ struct eventhandler_entry *eh_suspend;
+ struct eventhandler_entry *eh_resume;
+
struct resource *res;
bus_space_tag_t bus_tag;
@@ -72,8 +77,10 @@ struct amdsmu_softc {
uint32_t active_ip_blocks;
struct sysctl_oid *ip_blocks_sysctlnode;
size_t ip_block_count;
- struct sysctl_oid *ip_block_sysctlnodes[nitems(amdsmu_ip_blocks_names)];
- bool ip_blocks_active[nitems(amdsmu_ip_blocks_names)];
+ struct sysctl_oid *ip_block_sysctlnodes[
+ nitems(amdsmu_ip_blocks_names)];
+ bool ip_blocks_active[
+ nitems(amdsmu_ip_blocks_names)];
bus_space_handle_t metrics_space;
struct amdsmu_metrics metrics;
diff --git a/sys/dev/amdsmu/amdsmu_reg.h b/sys/dev/amdsmu/amdsmu_reg.h
index e685b34e6883..d45fa60941d5 100644
--- a/sys/dev/amdsmu/amdsmu_reg.h
+++ b/sys/dev/amdsmu/amdsmu_reg.h
@@ -45,6 +45,7 @@ enum amdsmu_res {
enum amdsmu_msg {
SMU_MSG_GETSMUVERSION = 0x02,
+ SMU_MSG_SLEEP_HINT = 0x03,
SMU_MSG_LOG_GETDRAM_ADDR_HI = 0x04,
SMU_MSG_LOG_GETDRAM_ADDR_LO = 0x05,
SMU_MSG_LOG_START = 0x06,