aboutsummarylogtreecommitdiffstats
path: root/9001-v5.15-s0ix-patch-2021-11-19.patch
diff options
context:
space:
mode:
Diffstat (limited to '9001-v5.15-s0ix-patch-2021-11-19.patch')
-rw-r--r--9001-v5.15-s0ix-patch-2021-11-19.patch1051
1 files changed, 1051 insertions, 0 deletions
diff --git a/9001-v5.15-s0ix-patch-2021-11-19.patch b/9001-v5.15-s0ix-patch-2021-11-19.patch
new file mode 100644
index 000000000000..13beb6dbb834
--- /dev/null
+++ b/9001-v5.15-s0ix-patch-2021-11-19.patch
@@ -0,0 +1,1051 @@
+From 62f3bba24251ed9351a6f90413f196b52d4475fe Mon Sep 17 00:00:00 2001
+From: Scott B <arglebargle@arglebargle.dev>
+Date: Fri, 19 Nov 2021 16:46:04 -0800
+Subject: [PATCH] v5.15 s0ix patch 2021-11-19
+
+Squashed commit of the following:
+
+commit ba41527a12621cb4e7124ce4afcf6aa4f991a769
+Author: Alex Deucher <alexander.deucher@amd.com>
+Date: Thu Nov 18 14:54:53 2021 -0500
+
+ drm/amdgpu/gfx9: switch to golden tsc registers for renoir+
+
+ Renoir and newer gfx9 APUs have new TSC register that is
+ not part of the gfxoff tile, so it can be read without
+ needing to disable gfx off.
+
+ Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit 8e2d97445c1620f1b9cd5283b9cb654afa3e4b91
+Author: Alex Deucher <alexander.deucher@amd.com>
+Date: Thu Nov 18 14:54:52 2021 -0500
+
+ drm/amdgpu/gfx10: add wraparound gpu counter check for APUs as well
+
+ Apply the same check we do for dGPUs for APUs as well.
+
+ Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+
+commit 462c4b0a294a94d38c3ea9e32f09eafe42777616
+Author: Julian Sikorski <belegdol+github@gmail.com>
+Date: Fri Nov 19 17:52:36 2021 +0100
+
+ GFXOFF check patch by Lijo Lazar
+
+commit 8baca2bf29ff89df4d7310caa156f49b85eac9c4
+Author: Sanket Goswami <Sanket.Goswami@amd.com>
+Date: Thu Oct 28 17:09:35 2021 +0530
+
+ platform/x86: amd-pmc: Add support for AMD Smart Trace Buffer (v5)
+
+ STB (Smart Trace Buffer), is a debug trace buffer which is used to help
+ isolate failures by analyzing the last feature that a system was running
+ before hitting a failure. This nonintrusive way is always running in the
+ background and trace is stored into the SoC.
+
+ This patch provides mechanism to access the STB buffer using the read
+ and write routines.
+
+ Co-developed-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
+ Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
+ Signed-off-by: Sanket Goswami <Sanket.Goswami@amd.com>
+
+commit 1aa4adac827e28d33352e47988c3d3311bfeab85
+Author: Sanket Goswami <Sanket.Goswami@amd.com>
+Date: Thu Oct 28 17:09:34 2021 +0530
+
+ platform/x86: amd-pmc: Store the pci_dev instance inside struct amd_pmc_dev
+
+ Store the root port information in amd_pmc_probe() so that the
+ information can be used across multiple routines.
+
+ Signed-off-by: Sanket Goswami <Sanket.Goswami@amd.com>
+
+commit 0e7044e4961c1c735e16f9c8033637cdcef839b3
+Author: Sanket Goswami <Sanket.Goswami@amd.com>
+Date: Thu Oct 28 17:09:33 2021 +0530
+
+ platform/x86: amd-pmc: Simplify error handling path
+
+ Handle error-exits in the amd_pmc_probe() so that the code duplication
+ is reduced.
+
+ Signed-off-by: Sanket Goswami <Sanket.Goswami@amd.com>
+
+commit 989a04253b89ace8343625e79b9a6682b615f922
+Author: Mario Limonciello <mario.limonciello@amd.com>
+Date: Sun Oct 31 20:48:53 2021 -0500
+
+ pinctrl: amd: Fix wakeups when IRQ is shared with SCI (v7)
+
+ On some Lenovo AMD Gen2 platforms the IRQ for the SCI and pinctrl drivers
+ are shared. Due to how the s2idle loop handling works, this case needs
+ an extra explicit check whether the interrupt was caused by SCI or by
+ the GPIO controller.
+
+ To fix this rework the existing IRQ handler function to function as a
+ checker and an IRQ handler depending on the calling arguments.
+
+ BugLink: https://gitlab.freedesktop.org/drm/amd/-/issues/1738
+ Reported-by: Joerie de Gram <j.de.gram@gmail.com>
+ Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+ Acked-by: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
+
+commit 926f0d2773e3d42a0863c05c3700e0665251db87
+Author: Mario Limonciello <mario.limonciello@amd.com>
+Date: Fri Oct 29 15:40:16 2021 -0500
+
+ ACPI: Add stubs for wakeup handler functions
+
+ The commit ddfd9dcf270c ("ACPI: PM: Add acpi_[un]register_wakeup_handler()")
+ added new functions for drivers to use during the s2idle wakeup path, but
+ didn't add stubs for when CONFIG_ACPI wasn't set.
+
+ Add those stubs in for other drivers to be able to use.
+
+ Fixes: ddfd9dcf270c ("ACPI: PM: Add acpi_[un]register_wakeup_handler()")
+ Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+ Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+
+commit e284369442c61048b06e31ece7282b032de09c29
+Author: Hans de Goede <hdegoede@redhat.com>
+Date: Tue Nov 2 16:32:56 2021 +0100
+
+ platform/x86: amd-pmc: Make CONFIG_AMD_PMC depend on RTC_CLASS
+
+ Since the "Add special handling for timer based S0i3 wakeup" changes
+ the amd-pmc code now relies on symbols from the RTC-class code,
+ add a dependency for this to Kconfig.
+
+ Fixes: 59348401ebed ("platform/x86: amd-pmc: Add special handling for timer based S0i3 wakeup")
+ Cc: Mario Limonciello <mario.limonciello@amd.com>
+ Reported-by: Randy Dunlap <rdunlap@infradead.org>
+ Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+ Acked-by: Mario Limonciello <mario.limonciello@amd.com>
+
+commit 7d269824781acfca610b81e3747833423a4b314a
+Author: Mario Limonciello <mario.limonciello@amd.com>
+Date: Tue Oct 26 12:14:43 2021 -0500
+
+ platform/x86: amd-pmc: Drop check for valid alarm time
+
+ This is already checked when calling rtc_read_alarm.
+
+ Suggested-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
+ Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+
+commit f62a21feb82e82bbdda66ac7b0ce04dab4b43e0b
+Author: Mario Limonciello <mario.limonciello@amd.com>
+Date: Tue Oct 26 12:14:42 2021 -0500
+
+ platform/x86: amd-pmc: Downgrade dev_info message to dev_dbg
+
+ For the majority of users this information will not be informative
+ as they've chosen to program the RTC before going to sleep.
+
+ Suggested-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
+ Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+
+commit c01d560f2b53e1519676b8c412802e1ce4ed6b02
+Author: Mario Limonciello <mario.limonciello@amd.com>
+Date: Tue Oct 26 12:14:41 2021 -0500
+
+ platform/x86: amd-pmc: fix compilation without CONFIG_RTC_SYSTOHC_DEVICE
+
+ If the configuration hasn't specified this parameter the rest of the new
+ RTC functionality should just be ignored.
+
+ Cc: Alexandre Belloni <alexandre.belloni@bootlin.com>
+ Suggested-by: Hans de Goede <hdegoede@redhat.com>
+ Fixes: 59348401ebed ("platform/x86: amd-pmc: Add special handling for timer based S0i3 wakeup")
+ Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+
+commit 0f8c1535f8317ef99ec51f11c00584a85bdf49fd
+Author: Mario Limonciello <mario.limonciello@amd.com>
+Date: Wed Oct 20 11:29:46 2021 -0500
+
+ platform/x86: amd-pmc: Add special handling for timer based S0i3 wakeup
+
+ RTC based wakeup from s0i3 doesn't work properly on some Green Sardine
+ platforms. Because of this, a newer SMU for Green Sardine has the ability
+ to pass wakeup time as argument of the upper 16 bits of OS_HINT message.
+
+ With older firmware setting the timer value in OS_HINT will cause firmware
+ to reject the hint, so only run this path on:
+ 1) Green Sardine
+ 2) Minimum SMU FW
+ 3) RTC alarm armed during s0i3 entry
+
+ Using this method has some limitations that the s0i3 wakeup will need to
+ be between 4 seconds and 18 hours, so check those boundary conditions as
+ well and abort the suspend if RTC is armed for too short or too long of a
+ duration.
+
+ Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+
+commit 13232abac47845187d59e20409f888899f0b36d3
+Author: Mario Limonciello <mario.limonciello@amd.com>
+Date: Wed Oct 20 11:29:45 2021 -0500
+
+ platform/x86: amd-pmc: adjust arguments for `amd_pmc_send_cmd`
+
+ Currently the "argument" for the "message" is listed as a boolean
+ value. This works well for the commands used currently, but an
+ additional upcoming command will pass more data in the message.
+
+ Expand it to be a full 32 bit value.
+
+ Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+
+commit 6d42af9d4af7b3e53c8d8c853effbcc84623b414
+Author: Hans de Goede <hdegoede@redhat.com>
+Date: Tue Sep 28 16:21:22 2021 +0200
+
+ platform/x86: amd-pmc: Fix compilation when CONFIG_DEBUGFS is disabled
+
+ The amd_pmc_get_smu_version() and amd_pmc_idlemask_read() functions are
+ used in the probe / suspend/resume code, so they are also used when
+ CONFIG_DEBUGFS is disabled, move them outside of the #ifdef CONFIG_DEBUGFS
+ block.
+
+ Note this purely moves the code to above the #ifdef CONFIG_DEBUGFS,
+ the code is completely unchanged.
+
+ Cc: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
+ Cc: Sanket Goswami <Sanket.Goswami@amd.com>
+ Reported-by: Nathan Chancellor <nathan@kernel.org>
+ Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+
+commit 26f5620d051d1c3d9824da3df5ad6f7865154d56
+Author: Mario Limonciello <mario.limonciello@amd.com>
+Date: Fri Sep 24 12:32:06 2021 -0500
+
+ ACPI: PM: s2idle: Don't report missing devices as failing constraints
+
+ ACPI tables may have entries for devices that are not physically
+ present but that can be connected. These devices shouldn't cause
+ constraints checking to fail.
+
+ Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+ Change-Id: I34f5ca978aab69ff0a0906191eec21649b19fe27
+
+commit 9b45888587b66d06c38c47958e7e503d0a367ad6
+Author: Sanket Goswami <Sanket.Goswami@amd.com>
+Date: Tue Sep 21 17:30:20 2021 +0530
+
+ platform/x86: amd-pmc: Add a message to print resume time info
+
+ Add a message to print the resume time information obtained from the
+ smu_metrics structure.
+
+ Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
+ Signed-off-by: Sanket Goswami <Sanket.Goswami@amd.com>
+
+commit 65e81196616f652d9b202f7af689129c1feb1212
+Author: Sanket Goswami <Sanket.Goswami@amd.com>
+Date: Tue Sep 21 17:29:10 2021 +0530
+
+ platform/x86: amd-pmc: Send command to dump data after clearing OS_HINT
+
+ It was reported that the resume stats received from the firmware are
+ always zero. This happens because the SMU expects the driver to send the
+ command to dump the log data after clearing the OS_HINT.
+
+ Adjust the order of the commands sent to SMU.
+
+ Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
+ Signed-off-by: Sanket Goswami <Sanket.Goswami@amd.com>
+
+commit 8bc5014976796c839be445928f13c9338dd49add
+Author: Sanket Goswami <Sanket.Goswami@amd.com>
+Date: Thu Sep 16 18:11:30 2021 +0530
+
+ platform/x86: amd-pmc: Check s0i3 cycle status
+
+ As the PM firmware returns the status of the last s0i3 in the smu_metrics
+ structure, the existing name "s0i3_cyclecount" seems to be a misnomer.
+ Change it accordingly to "s0i3_last_entry_status".
+
+ Signed-off-by: Sanket Goswami <Sanket.Goswami@amd.com>
+ Acked-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
+
+commit e47fa03b6683ef26e4fe6a74432920d0f71b2795
+Author: Sanket Goswami <Sanket.Goswami@amd.com>
+Date: Thu Sep 16 18:10:02 2021 +0530
+
+ platform/x86: amd-pmc: Export Idlemask values based on the APU
+
+ IdleMask is the metric used by the PM firmware to know the status of each
+ of the Hardware IP blocks monitored by the PM firmware.
+
+ Knowing this value is key to get the information of s2idle suspend/resume
+ status. This value is mapped to PMC scratch registers, retrieve them
+ accordingly based on the CPU family and the underlying firmware support.
+
+ Co-developed-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
+ Signed-off-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
+ Signed-off-by: Sanket Goswami <Sanket.Goswami@amd.com>
+ Acked-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
+ Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
+
+commit b10ad23222811cf6fd409228990eaa651f54e1b8
+Author: Mario Limonciello <mario.limonciello@amd.com>
+Date: Wed Sep 15 16:52:16 2021 -0500
+
+ ACPI: processor idle: Allow playing dead in C3
+
+ commit 1a022e3f1be1 ("idle, x86: Allow off-lined CPU to enter
+ deeper C states") originally allowed offlined CPUs to play dead
+ up to ACPI C2. Although this improves power consumption of offlined
+ CPUs, it does not allow the CPUs to get into the deepest state
+ on AMD platforms blocking s0i3 entry.
+
+ BugLink: https://gitlab.freedesktop.org/drm/amd/-/issues/1708
+ Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+---
+ drivers/acpi/processor_idle.c | 3 +-
+ drivers/acpi/x86/s2idle.c | 6 +
+ drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 15 +-
+ drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 49 +++-
+ drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c | 5 +-
+ drivers/pinctrl/pinctrl-amd.c | 29 ++-
+ drivers/platform/x86/Kconfig | 2 +-
+ drivers/platform/x86/amd-pmc.c | 301 ++++++++++++++++++++--
+ include/linux/acpi.h | 9 +
+ 9 files changed, 380 insertions(+), 39 deletions(-)
+
+diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
+index f37fba9e5ba0..9d378dc9e928 100644
+--- a/drivers/acpi/processor_idle.c
++++ b/drivers/acpi/processor_idle.c
+@@ -789,7 +789,8 @@ static int acpi_processor_setup_cstates(struct acpi_processor *pr)
+ state->enter = acpi_idle_enter;
+
+ state->flags = 0;
+- if (cx->type == ACPI_STATE_C1 || cx->type == ACPI_STATE_C2) {
++ if (cx->type == ACPI_STATE_C1 || cx->type == ACPI_STATE_C2
++ || cx->type == ACPI_STATE_C3) {
+ state->enter_dead = acpi_idle_play_dead;
+ drv->safe_state_index = count;
+ }
+diff --git a/drivers/acpi/x86/s2idle.c b/drivers/acpi/x86/s2idle.c
+index 1c48358b43ba..0b65d4623214 100644
+--- a/drivers/acpi/x86/s2idle.c
++++ b/drivers/acpi/x86/s2idle.c
+@@ -309,6 +309,12 @@ static void lpi_check_constraints(void)
+ continue;
+ }
+
++ if (!acpi_get_first_physical_node(adev)) {
++ acpi_handle_debug(handle, "LPI: Device is not physically present\n");
++ lpi_constraints_table[i].handle = NULL;
++ continue;
++ }
++
+ if (adev->power.state < lpi_constraints_table[i].min_dstate)
+ acpi_handle_info(handle,
+ "LPI: Constraint not met; min power state:%s current power state:%s\n",
+diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
+index 16dbe593cba2..970d59a21005 100644
+--- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
+@@ -7729,8 +7729,19 @@ static uint64_t gfx_v10_0_get_gpu_clock_counter(struct amdgpu_device *adev)
+ switch (adev->asic_type) {
+ case CHIP_VANGOGH:
+ case CHIP_YELLOW_CARP:
+- clock = (uint64_t)RREG32_SOC15(SMUIO, 0, mmGOLDEN_TSC_COUNT_LOWER_Vangogh) |
+- ((uint64_t)RREG32_SOC15(SMUIO, 0, mmGOLDEN_TSC_COUNT_UPPER_Vangogh) << 32ULL);
++ preempt_disable();
++ clock_hi = RREG32_SOC15_NO_KIQ(SMUIO, 0, mmGOLDEN_TSC_COUNT_UPPER_Vangogh);
++ clock_lo = RREG32_SOC15_NO_KIQ(SMUIO, 0, mmGOLDEN_TSC_COUNT_LOWER_Vangogh);
++ hi_check = RREG32_SOC15_NO_KIQ(SMUIO, 0, mmGOLDEN_TSC_COUNT_UPPER_Vangogh);
++ /* The SMUIO TSC clock frequency is 100MHz, which sets 32-bit carry over
++ * roughly every 42 seconds.
++ */
++ if (hi_check != clock_hi) {
++ clock_lo = RREG32_SOC15_NO_KIQ(SMUIO, 0, mmGOLDEN_TSC_COUNT_LOWER_Vangogh);
++ clock_hi = hi_check;
++ }
++ preempt_enable();
++ clock = clock_lo | (clock_hi << 32ULL);
+ break;
+ default:
+ preempt_disable();
+diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
+index 025184a556ee..3fee7ea7f05e 100644
+--- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
+@@ -140,6 +140,11 @@ MODULE_FIRMWARE("amdgpu/aldebaran_rlc.bin");
+ #define mmTCP_CHAN_STEER_5_ARCT 0x0b0c
+ #define mmTCP_CHAN_STEER_5_ARCT_BASE_IDX 0
+
++#define mmGOLDEN_TSC_COUNT_UPPER_Renoir 0x0025
++#define mmGOLDEN_TSC_COUNT_UPPER_Renoir_BASE_IDX 1
++#define mmGOLDEN_TSC_COUNT_LOWER_Renoir 0x0026
++#define mmGOLDEN_TSC_COUNT_LOWER_Renoir_BASE_IDX 1
++
+ enum ta_ras_gfx_subblock {
+ /*CPC*/
+ TA_RAS_BLOCK__GFX_CPC_INDEX_START = 0,
+@@ -4228,19 +4233,39 @@ static uint64_t gfx_v9_0_kiq_read_clock(struct amdgpu_device *adev)
+
+ static uint64_t gfx_v9_0_get_gpu_clock_counter(struct amdgpu_device *adev)
+ {
+- uint64_t clock;
+-
+- amdgpu_gfx_off_ctrl(adev, false);
+- mutex_lock(&adev->gfx.gpu_clock_mutex);
+- if (adev->asic_type == CHIP_VEGA10 && amdgpu_sriov_runtime(adev)) {
+- clock = gfx_v9_0_kiq_read_clock(adev);
+- } else {
+- WREG32_SOC15(GC, 0, mmRLC_CAPTURE_GPU_CLOCK_COUNT, 1);
+- clock = (uint64_t)RREG32_SOC15(GC, 0, mmRLC_GPU_CLOCK_COUNT_LSB) |
+- ((uint64_t)RREG32_SOC15(GC, 0, mmRLC_GPU_CLOCK_COUNT_MSB) << 32ULL);
++ uint64_t clock, clock_lo, clock_hi, hi_check;
++
++ switch (adev->asic_type) {
++ case CHIP_RENOIR:
++ preempt_disable();
++ clock_hi = RREG32_SOC15_NO_KIQ(SMUIO, 0, mmGOLDEN_TSC_COUNT_UPPER_Renoir);
++ clock_lo = RREG32_SOC15_NO_KIQ(SMUIO, 0, mmGOLDEN_TSC_COUNT_LOWER_Renoir);
++ hi_check = RREG32_SOC15_NO_KIQ(SMUIO, 0, mmGOLDEN_TSC_COUNT_UPPER_Renoir);
++ /* The SMUIO TSC clock frequency is 100MHz, which sets 32-bit carry over
++ * roughly every 42 seconds.
++ */
++ if (hi_check != clock_hi) {
++ clock_lo = RREG32_SOC15_NO_KIQ(SMUIO, 0, mmGOLDEN_TSC_COUNT_LOWER_Renoir);
++ clock_hi = hi_check;
++ }
++ preempt_enable();
++ clock = clock_lo | (clock_hi << 32ULL);
++ break;
++ default:
++ amdgpu_gfx_off_ctrl(adev, false);
++ mutex_lock(&adev->gfx.gpu_clock_mutex);
++ if (adev->asic_type == CHIP_VEGA10 && amdgpu_sriov_runtime(adev)) {
++ clock = gfx_v9_0_kiq_read_clock(adev);
++ } else {
++ WREG32_SOC15(GC, 0, mmRLC_CAPTURE_GPU_CLOCK_COUNT, 1);
++ clock = (uint64_t)RREG32_SOC15(GC, 0, mmRLC_GPU_CLOCK_COUNT_LSB) |
++ ((uint64_t)RREG32_SOC15(GC, 0, mmRLC_GPU_CLOCK_COUNT_MSB) << 32ULL);
++ }
++ mutex_unlock(&adev->gfx.gpu_clock_mutex);
++ amdgpu_gfx_off_ctrl(adev, true);
++ break;
++ ((uint64_t)RREG32_SOC15(GC, 0, mmRLC_GPU_CLOCK_COUNT_MSB) << 32ULL);
+ }
+- mutex_unlock(&adev->gfx.gpu_clock_mutex);
+- amdgpu_gfx_off_ctrl(adev, true);
+ return clock;
+ }
+
+diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
+index 04863a797115..8c54041e6c6b 100644
+--- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
++++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
+@@ -277,8 +277,11 @@ static int smu_dpm_set_power_gate(void *handle,
+ struct smu_context *smu = handle;
+ int ret = 0;
+
+- if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled)
++ if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled) {
++ WARN(true, "SMU uninitialized but power %s requested for %u!\n",
++ gate ? "gate" : "ungate", block_type);
+ return -EOPNOTSUPP;
++ }
+
+ switch (block_type) {
+ /*
+diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c
+index bae9d429b813..ecab9064a845 100644
+--- a/drivers/pinctrl/pinctrl-amd.c
++++ b/drivers/pinctrl/pinctrl-amd.c
+@@ -598,14 +598,14 @@ static struct irq_chip amd_gpio_irqchip = {
+
+ #define PIN_IRQ_PENDING (BIT(INTERRUPT_STS_OFF) | BIT(WAKE_STS_OFF))
+
+-static irqreturn_t amd_gpio_irq_handler(int irq, void *dev_id)
++static bool do_amd_gpio_irq_handler(int irq, void *dev_id)
+ {
+ struct amd_gpio *gpio_dev = dev_id;
+ struct gpio_chip *gc = &gpio_dev->gc;
+- irqreturn_t ret = IRQ_NONE;
+ unsigned int i, irqnr;
+ unsigned long flags;
+ u32 __iomem *regs;
++ bool ret = false;
+ u32 regval;
+ u64 status, mask;
+
+@@ -627,6 +627,14 @@ static irqreturn_t amd_gpio_irq_handler(int irq, void *dev_id)
+ /* Each status bit covers four pins */
+ for (i = 0; i < 4; i++) {
+ regval = readl(regs + i);
++ /* caused wake on resume context for shared IRQ */
++ if (irq < 0 && (regval & BIT(WAKE_STS_OFF))) {
++ dev_dbg(&gpio_dev->pdev->dev,
++ "Waking due to GPIO %d: 0x%x",
++ irqnr + i, regval);
++ return true;
++ }
++
+ if (!(regval & PIN_IRQ_PENDING) ||
+ !(regval & BIT(INTERRUPT_MASK_OFF)))
+ continue;
+@@ -650,9 +658,12 @@ static irqreturn_t amd_gpio_irq_handler(int irq, void *dev_id)
+ }
+ writel(regval, regs + i);
+ raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
+- ret = IRQ_HANDLED;
++ ret = true;
+ }
+ }
++ /* did not cause wake on resume context for shared IRQ */
++ if (irq < 0)
++ return false;
+
+ /* Signal EOI to the GPIO unit */
+ raw_spin_lock_irqsave(&gpio_dev->lock, flags);
+@@ -664,6 +675,16 @@ static irqreturn_t amd_gpio_irq_handler(int irq, void *dev_id)
+ return ret;
+ }
+
++static irqreturn_t amd_gpio_irq_handler(int irq, void *dev_id)
++{
++ return IRQ_RETVAL(do_amd_gpio_irq_handler(irq, dev_id));
++}
++
++static bool __maybe_unused amd_gpio_check_wake(void *dev_id)
++{
++ return do_amd_gpio_irq_handler(-1, dev_id);
++}
++
+ static int amd_get_groups_count(struct pinctrl_dev *pctldev)
+ {
+ struct amd_gpio *gpio_dev = pinctrl_dev_get_drvdata(pctldev);
+@@ -1033,6 +1054,7 @@ static int amd_gpio_probe(struct platform_device *pdev)
+ goto out2;
+
+ platform_set_drvdata(pdev, gpio_dev);
++ acpi_register_wakeup_handler(gpio_dev->irq, amd_gpio_check_wake, gpio_dev);
+
+ dev_dbg(&pdev->dev, "amd gpio driver loaded\n");
+ return ret;
+@@ -1050,6 +1072,7 @@ static int amd_gpio_remove(struct platform_device *pdev)
+ gpio_dev = platform_get_drvdata(pdev);
+
+ gpiochip_remove(&gpio_dev->gc);
++ acpi_unregister_wakeup_handler(amd_gpio_check_wake, gpio_dev);
+
+ return 0;
+ }
+diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
+index e21ea3d23e6f..4cc2782635ec 100644
+--- a/drivers/platform/x86/Kconfig
++++ b/drivers/platform/x86/Kconfig
+@@ -170,7 +170,7 @@ config ACER_WMI
+
+ config AMD_PMC
+ tristate "AMD SoC PMC driver"
+- depends on ACPI && PCI
++ depends on ACPI && PCI && RTC_CLASS
+ help
+ The driver provides support for AMD Power Management Controller
+ primarily responsible for S2Idle transactions that are driven from
+diff --git a/drivers/platform/x86/amd-pmc.c b/drivers/platform/x86/amd-pmc.c
+index fc95620101e8..5d1ff04152de 100644
+--- a/drivers/platform/x86/amd-pmc.c
++++ b/drivers/platform/x86/amd-pmc.c
+@@ -17,9 +17,11 @@
+ #include <linux/delay.h>
+ #include <linux/io.h>
+ #include <linux/iopoll.h>
++#include <linux/limits.h>
+ #include <linux/module.h>
+ #include <linux/pci.h>
+ #include <linux/platform_device.h>
++#include <linux/rtc.h>
+ #include <linux/suspend.h>
+ #include <linux/seq_file.h>
+ #include <linux/uaccess.h>
+@@ -29,6 +31,16 @@
+ #define AMD_PMC_REGISTER_RESPONSE 0x980
+ #define AMD_PMC_REGISTER_ARGUMENT 0x9BC
+
++/* PMC Scratch Registers */
++#define AMD_PMC_SCRATCH_REG_CZN 0x94
++#define AMD_PMC_SCRATCH_REG_YC 0xD14
++
++/* STB Registers */
++#define AMD_PMC_STB_INDEX_ADDRESS 0xF8
++#define AMD_PMC_STB_INDEX_DATA 0xFC
++#define AMD_PMC_STB_PMI_0 0x03E30600
++#define AMD_PMC_STB_PREDEF 0xC6000001
++
+ /* Base address of SMU for mapping physical address to virtual address */
+ #define AMD_PMC_SMU_INDEX_ADDRESS 0xB8
+ #define AMD_PMC_SMU_INDEX_DATA 0xBC
+@@ -76,6 +88,7 @@
+ #define SOC_SUBSYSTEM_IP_MAX 12
+ #define DELAY_MIN_US 2000
+ #define DELAY_MAX_US 3000
++#define FIFO_SIZE 4096
+ enum amd_pmc_def {
+ MSG_TEST = 0x01,
+ MSG_OS_HINT_PCO,
+@@ -110,15 +123,26 @@ struct amd_pmc_dev {
+ u32 base_addr;
+ u32 cpu_id;
+ u32 active_ips;
++/* SMU version information */
++ u16 major;
++ u16 minor;
++ u16 rev;
+ struct device *dev;
++ struct pci_dev *rdev;
+ struct mutex lock; /* generic mutex lock */
+ #if IS_ENABLED(CONFIG_DEBUG_FS)
+ struct dentry *dbgfs_dir;
+ #endif /* CONFIG_DEBUG_FS */
+ };
+
++static bool enable_stb;
++module_param(enable_stb, bool, 0644);
++MODULE_PARM_DESC(enable_stb, "Enable the STB debug mechanism");
++
+ static struct amd_pmc_dev pmc;
+-static int amd_pmc_send_cmd(struct amd_pmc_dev *dev, bool set, u32 *data, u8 msg, bool ret);
++static int amd_pmc_send_cmd(struct amd_pmc_dev *dev, u32 arg, u32 *data, u8 msg, bool ret);
++static int amd_pmc_write_stb(struct amd_pmc_dev *dev, u32 data);
++static int amd_pmc_read_stb(struct amd_pmc_dev *dev, u32 *buf);
+
+ static inline u32 amd_pmc_reg_read(struct amd_pmc_dev *dev, int reg_offset)
+ {
+@@ -133,7 +157,7 @@ static inline void amd_pmc_reg_write(struct amd_pmc_dev *dev, int reg_offset, u3
+ struct smu_metrics {
+ u32 table_version;
+ u32 hint_count;
+- u32 s0i3_cyclecount;
++ u32 s0i3_last_entry_status;
+ u32 timein_s0i2;
+ u64 timeentering_s0i3_lastcapture;
+ u64 timeentering_s0i3_totaltime;
+@@ -147,6 +171,97 @@ struct smu_metrics {
+ u64 timecondition_notmet_totaltime[SOC_SUBSYSTEM_IP_MAX];
+ } __packed;
+
++static int amd_pmc_get_smu_version(struct amd_pmc_dev *dev)
++{
++ int rc;
++ u32 val;
++
++ rc = amd_pmc_send_cmd(dev, 0, &val, SMU_MSG_GETSMUVERSION, 1);
++ if (rc)
++ return rc;
++
++ dev->major = (val >> 16) & GENMASK(15, 0);
++ dev->minor = (val >> 8) & GENMASK(7, 0);
++ dev->rev = (val >> 0) & GENMASK(7, 0);
++
++ dev_dbg(dev->dev, "SMU version is %u.%u.%u\n", dev->major, dev->minor, dev->rev);
++
++ return 0;
++}
++
++static int amd_pmc_stb_debugfs_open(struct inode *inode, struct file *filp)
++{
++ struct amd_pmc_dev *dev = filp->f_inode->i_private;
++ u32 size = FIFO_SIZE * sizeof(u32);
++ u32 *buf;
++ int rc;
++
++ buf = kzalloc(size, GFP_KERNEL);
++ if (!buf)
++ return -ENOMEM;
++
++ rc = amd_pmc_read_stb(dev, buf);
++ if (rc)
++ goto out;
++
++ filp->private_data = buf;
++ return 0;
++
++out:
++ kfree(buf);
++ return rc;
++}
++
++static ssize_t amd_pmc_stb_debugfs_read(struct file *filp, char __user *buf, size_t size,
++ loff_t *pos)
++{
++ if (!filp->private_data)
++ return -EINVAL;
++
++ return simple_read_from_buffer(buf, size, pos, filp->private_data,
++ FIFO_SIZE * sizeof(u32));
++}
++
++static int amd_pmc_stb_debugfs_release(struct inode *inode, struct file *filp)
++{
++ kfree(filp->private_data);
++ filp->private_data = NULL;
++
++ return 0;
++}
++
++const struct file_operations amd_pmc_stb_debugfs_fops = {
++ .owner = THIS_MODULE,
++ .open = amd_pmc_stb_debugfs_open,
++ .read = amd_pmc_stb_debugfs_read,
++ .release = amd_pmc_stb_debugfs_release,
++};
++
++static int amd_pmc_idlemask_read(struct amd_pmc_dev *pdev, struct device *dev,
++ struct seq_file *s)
++{
++ u32 val;
++
++ switch (pdev->cpu_id) {
++ case AMD_CPU_ID_CZN:
++ val = amd_pmc_reg_read(pdev, AMD_PMC_SCRATCH_REG_CZN);
++ break;
++ case AMD_CPU_ID_YC:
++ val = amd_pmc_reg_read(pdev, AMD_PMC_SCRATCH_REG_YC);
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ if (dev)
++ dev_dbg(pdev->dev, "SMU idlemask s0i3: 0x%x\n", val);
++
++ if (s)
++ seq_printf(s, "SMU idlemask : 0x%x\n", val);
++
++ return 0;
++}
++
+ #ifdef CONFIG_DEBUG_FS
+ static int smu_fw_info_show(struct seq_file *s, void *unused)
+ {
+@@ -162,9 +277,12 @@ static int smu_fw_info_show(struct seq_file *s, void *unused)
+ seq_puts(s, "\n=== SMU Statistics ===\n");
+ seq_printf(s, "Table Version: %d\n", table.table_version);
+ seq_printf(s, "Hint Count: %d\n", table.hint_count);
+- seq_printf(s, "S0i3 Cycle Count: %d\n", table.s0i3_cyclecount);
++ seq_printf(s, "Last S0i3 Status: %s\n", table.s0i3_last_entry_status ? "Success" :
++ "Unknown/Fail");
+ seq_printf(s, "Time (in us) to S0i3: %lld\n", table.timeentering_s0i3_lastcapture);
+ seq_printf(s, "Time (in us) in S0i3: %lld\n", table.timein_s0i3_lastcapture);
++ seq_printf(s, "Time (in us) to resume from S0i3: %lld\n",
++ table.timeto_resume_to_os_lastcapture);
+
+ seq_puts(s, "\n=== Active time (in us) ===\n");
+ for (idx = 0 ; idx < SOC_SUBSYSTEM_IP_MAX ; idx++) {
+@@ -201,6 +319,23 @@ static int s0ix_stats_show(struct seq_file *s, void *unused)
+ }
+ DEFINE_SHOW_ATTRIBUTE(s0ix_stats);
+
++static int amd_pmc_idlemask_show(struct seq_file *s, void *unused)
++{
++ struct amd_pmc_dev *dev = s->private;
++ int rc;
++
++ if (dev->major > 56 || (dev->major >= 55 && dev->minor >= 37)) {
++ rc = amd_pmc_idlemask_read(dev, NULL, s);
++ if (rc)
++ return rc;
++ } else {
++ seq_puts(s, "Unsupported SMU version for Idlemask\n");
++ }
++
++ return 0;
++}
++DEFINE_SHOW_ATTRIBUTE(amd_pmc_idlemask);
++
+ static void amd_pmc_dbgfs_unregister(struct amd_pmc_dev *dev)
+ {
+ debugfs_remove_recursive(dev->dbgfs_dir);
+@@ -213,6 +348,12 @@ static void amd_pmc_dbgfs_register(struct amd_pmc_dev *dev)
+ &smu_fw_info_fops);
+ debugfs_create_file("s0ix_stats", 0644, dev->dbgfs_dir, dev,
+ &s0ix_stats_fops);
++ debugfs_create_file("amd_pmc_idlemask", 0644, dev->dbgfs_dir, dev,
++ &amd_pmc_idlemask_fops);
++ /* Enable STB only when the module_param is set */
++ if (enable_stb)
++ debugfs_create_file("stb_read", 0644, dev->dbgfs_dir, dev,
++ &amd_pmc_stb_debugfs_fops);
+ }
+ #else
+ static inline void amd_pmc_dbgfs_register(struct amd_pmc_dev *dev)
+@@ -264,7 +405,7 @@ static void amd_pmc_dump_registers(struct amd_pmc_dev *dev)
+ dev_dbg(dev->dev, "AMD_PMC_REGISTER_MESSAGE:%x\n", value);
+ }
+
+-static int amd_pmc_send_cmd(struct amd_pmc_dev *dev, bool set, u32 *data, u8 msg, bool ret)
++static int amd_pmc_send_cmd(struct amd_pmc_dev *dev, u32 arg, u32 *data, u8 msg, bool ret)
+ {
+ int rc;
+ u32 val;
+@@ -283,7 +424,7 @@ static int amd_pmc_send_cmd(struct amd_pmc_dev *dev, bool set, u32 *data, u8 msg
+ amd_pmc_reg_write(dev, AMD_PMC_REGISTER_RESPONSE, 0);
+
+ /* Write argument into response register */
+- amd_pmc_reg_write(dev, AMD_PMC_REGISTER_ARGUMENT, set);
++ amd_pmc_reg_write(dev, AMD_PMC_REGISTER_ARGUMENT, arg);
+
+ /* Write message ID to message ID register */
+ amd_pmc_reg_write(dev, AMD_PMC_REGISTER_MESSAGE, msg);
+@@ -339,21 +480,79 @@ static int amd_pmc_get_os_hint(struct amd_pmc_dev *dev)
+ return -EINVAL;
+ }
+
++static int amd_pmc_verify_czn_rtc(struct amd_pmc_dev *pdev, u32 *arg)
++{
++ struct rtc_device *rtc_device;
++ time64_t then, now, duration;
++ struct rtc_wkalrm alarm;
++ struct rtc_time tm;
++ int rc;
++
++ if (pdev->major < 64 || (pdev->major == 64 && pdev->minor < 53))
++ return 0;
++
++ rtc_device = rtc_class_open("rtc0");
++ if (!rtc_device)
++ return 0;
++ rc = rtc_read_alarm(rtc_device, &alarm);
++ if (rc)
++ return rc;
++ if (!alarm.enabled) {
++ dev_dbg(pdev->dev, "alarm not enabled\n");
++ return 0;
++ }
++ rc = rtc_read_time(rtc_device, &tm);
++ if (rc)
++ return rc;
++ then = rtc_tm_to_time64(&alarm.time);
++ now = rtc_tm_to_time64(&tm);
++ duration = then-now;
++
++ /* in the past */
++ if (then < now)
++ return 0;
++
++ /* will be stored in upper 16 bits of s0i3 hint argument,
++ * so timer wakeup from s0i3 is limited to ~18 hours or less
++ */
++ if (duration <= 4 || duration > U16_MAX)
++ return -EINVAL;
++
++ *arg |= (duration << 16);
++ rc = rtc_alarm_irq_enable(rtc_device, 0);
++ dev_dbg(pdev->dev, "wakeup timer programmed for %lld seconds\n", duration);
++
++ return rc;
++}
++
+ static int __maybe_unused amd_pmc_suspend(struct device *dev)
+ {
+ struct amd_pmc_dev *pdev = dev_get_drvdata(dev);
+ int rc;
+ u8 msg;
++ u32 arg = 1;
+
+ /* Reset and Start SMU logging - to monitor the s0i3 stats */
+ amd_pmc_send_cmd(pdev, 0, NULL, SMU_MSG_LOG_RESET, 0);
+ amd_pmc_send_cmd(pdev, 0, NULL, SMU_MSG_LOG_START, 0);
+
++ /* Activate CZN specific RTC functionality */
++ if (pdev->cpu_id == AMD_CPU_ID_CZN) {
++ rc = amd_pmc_verify_czn_rtc(pdev, &arg);
++ if (rc < 0)
++ return rc;
++ }
++
++ /* Dump the IdleMask before we send hint to SMU */
++ amd_pmc_idlemask_read(pdev, dev, NULL);
+ msg = amd_pmc_get_os_hint(pdev);
+- rc = amd_pmc_send_cmd(pdev, 1, NULL, msg, 0);
++ rc = amd_pmc_send_cmd(pdev, arg, NULL, msg, 0);
+ if (rc)
+ dev_err(pdev->dev, "suspend failed\n");
+
++ if (enable_stb)
++ amd_pmc_write_stb(pdev, AMD_PMC_STB_PREDEF);
++
+ return rc;
+ }
+
+@@ -363,14 +562,21 @@ static int __maybe_unused amd_pmc_resume(struct device *dev)
+ int rc;
+ u8 msg;
+
+- /* Let SMU know that we are looking for stats */
+- amd_pmc_send_cmd(pdev, 0, NULL, SMU_MSG_LOG_DUMP_DATA, 0);
+-
+ msg = amd_pmc_get_os_hint(pdev);
+ rc = amd_pmc_send_cmd(pdev, 0, NULL, msg, 0);
+ if (rc)
+ dev_err(pdev->dev, "resume failed\n");
+
++ /* Let SMU know that we are looking for stats */
++ amd_pmc_send_cmd(pdev, 0, NULL, SMU_MSG_LOG_DUMP_DATA, 0);
++
++ /* Dump the IdleMask to see the blockers */
++ amd_pmc_idlemask_read(pdev, dev, NULL);
++
++ /* Write data incremented by 1 to distinguish in stb_read */
++ if (enable_stb)
++ amd_pmc_write_stb(pdev, AMD_PMC_STB_PREDEF + 1);
++
+ return 0;
+ }
+
+@@ -387,6 +593,57 @@ static const struct pci_device_id pmc_pci_ids[] = {
+ { }
+ };
+
++static int amd_pmc_write_stb(struct amd_pmc_dev *dev, u32 data)
++{
++ int rc;
++
++ rc = pci_write_config_dword(dev->rdev, AMD_PMC_STB_INDEX_ADDRESS, AMD_PMC_STB_PMI_0);
++ if (rc) {
++ dev_err(dev->dev, "failed to write addr in stb: 0x%X\n",
++ AMD_PMC_STB_INDEX_ADDRESS);
++ pci_dev_put(dev->rdev);
++ return pcibios_err_to_errno(rc);
++ }
++
++ rc = pci_write_config_dword(dev->rdev, AMD_PMC_STB_INDEX_DATA, data);
++ if (rc) {
++ dev_err(dev->dev, "failed to write data in stb: 0x%X\n",
++ AMD_PMC_STB_INDEX_DATA);
++ pci_dev_put(dev->rdev);
++ return pcibios_err_to_errno(rc);
++ }
++
++ return 0;
++}
++
++static int amd_pmc_read_stb(struct amd_pmc_dev *dev, u32 *buf)
++{
++ int i, err;
++ u32 value;
++
++ err = pci_write_config_dword(dev->rdev, AMD_PMC_STB_INDEX_ADDRESS, AMD_PMC_STB_PMI_0);
++ if (err) {
++ dev_err(dev->dev, "error writing addr to stb: 0x%X\n",
++ AMD_PMC_STB_INDEX_ADDRESS);
++ pci_dev_put(dev->rdev);
++ return pcibios_err_to_errno(err);
++ }
++
++ for (i = 0; i < FIFO_SIZE; i++) {
++ err = pci_read_config_dword(dev->rdev, AMD_PMC_STB_INDEX_DATA, &value);
++ if (err) {
++ dev_err(dev->dev, "error reading data from stb: 0x%X\n",
++ AMD_PMC_STB_INDEX_DATA);
++ pci_dev_put(dev->rdev);
++ return pcibios_err_to_errno(err);
++ }
++
++ *buf++ = value;
++ }
++
++ return 0;
++}
++
+ static int amd_pmc_probe(struct platform_device *pdev)
+ {
+ struct amd_pmc_dev *dev = &pmc;
+@@ -400,22 +657,23 @@ static int amd_pmc_probe(struct platform_device *pdev)
+
+ rdev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(0, 0));
+ if (!rdev || !pci_match_id(pmc_pci_ids, rdev)) {
+- pci_dev_put(rdev);
+- return -ENODEV;
++ err = -ENODEV;
++ goto err_pci_dev_put;
+ }
+
+ dev->cpu_id = rdev->device;
++ dev->rdev = rdev;
+ err = pci_write_config_dword(rdev, AMD_PMC_SMU_INDEX_ADDRESS, AMD_PMC_BASE_ADDR_LO);
+ if (err) {
+ dev_err(dev->dev, "error writing to 0x%x\n", AMD_PMC_SMU_INDEX_ADDRESS);
+- pci_dev_put(rdev);
+- return pcibios_err_to_errno(err);
++ err = pcibios_err_to_errno(err);
++ goto err_pci_dev_put;
+ }
+
+ err = pci_read_config_dword(rdev, AMD_PMC_SMU_INDEX_DATA, &val);
+ if (err) {
+- pci_dev_put(rdev);
+- return pcibios_err_to_errno(err);
++ err = pcibios_err_to_errno(err);
++ goto err_pci_dev_put;
+ }
+
+ base_addr_lo = val & AMD_PMC_BASE_ADDR_HI_MASK;
+@@ -423,14 +681,14 @@ static int amd_pmc_probe(struct platform_device *pdev)
+ err = pci_write_config_dword(rdev, AMD_PMC_SMU_INDEX_ADDRESS, AMD_PMC_BASE_ADDR_HI);
+ if (err) {
+ dev_err(dev->dev, "error writing to 0x%x\n", AMD_PMC_SMU_INDEX_ADDRESS);
+- pci_dev_put(rdev);
+- return pcibios_err_to_errno(err);
++ err = pcibios_err_to_errno(err);
++ goto err_pci_dev_put;
+ }
+
+ err = pci_read_config_dword(rdev, AMD_PMC_SMU_INDEX_DATA, &val);
+ if (err) {
+- pci_dev_put(rdev);
+- return pcibios_err_to_errno(err);
++ err = pcibios_err_to_errno(err);
++ goto err_pci_dev_put;
+ }
+
+ base_addr_hi = val & AMD_PMC_BASE_ADDR_LO_MASK;
+@@ -457,9 +715,14 @@ static int amd_pmc_probe(struct platform_device *pdev)
+ if (err)
+ dev_err(dev->dev, "SMU debugging info not supported on this platform\n");
+
++ amd_pmc_get_smu_version(dev);
+ platform_set_drvdata(pdev, dev);
+ amd_pmc_dbgfs_register(dev);
+ return 0;
++
++err_pci_dev_put:
++ pci_dev_put(rdev);
++ return err;
+ }
+
+ static int amd_pmc_remove(struct platform_device *pdev)
+diff --git a/include/linux/acpi.h b/include/linux/acpi.h
+index 974d497a897d..6224b1e32681 100644
+--- a/include/linux/acpi.h
++++ b/include/linux/acpi.h
+@@ -976,6 +976,15 @@ static inline int acpi_get_local_address(acpi_handle handle, u32 *addr)
+ return -ENODEV;
+ }
+
++static inline int acpi_register_wakeup_handler(int wake_irq,
++ bool (*wakeup)(void *context), void *context)
++{
++ return -ENXIO;
++}
++
++static inline void acpi_unregister_wakeup_handler(
++ bool (*wakeup)(void *context), void *context) { }
++
+ #endif /* !CONFIG_ACPI */
+
+ #ifdef CONFIG_ACPI_HOTPLUG_IOAPIC
+--
+2.34.0
+