]> git.dujemihanovic.xyz Git - linux.git/commitdiff
soundwire: amd: fix for wake interrupt handling for clockstop mode
authorVijendar Mukunda <Vijendar.Mukunda@amd.com>
Wed, 27 Mar 2024 06:31:43 +0000 (12:01 +0530)
committerVinod Koul <vkoul@kernel.org>
Thu, 28 Mar 2024 18:10:33 +0000 (23:40 +0530)
When SoundWire Wake interrupt is enabled along with SoundWire Wake
enable register, SoundWire wake interrupt will be reported
when SoundWire manager is in D3 state and ACP is in D3 state.

When SoundWire Wake interrupt is reported, it will invoke runtime
resume of the SoundWire manager device.

In case of system level suspend, for ClockStop Mode SoundWire Wake
interrupt should be disabled.
It should be enabled only for runtime suspend scenario.
Change wake interrupt enable/disable sequence for ClockStop Mode in
system level suspend and runtime suspend sceanrio.

Fixes: 9cf1efc5ed2d ("soundwire: amd: add pm_prepare callback and pm ops support")
Signed-off-by: Vijendar Mukunda <Vijendar.Mukunda@amd.com>
Link: https://lore.kernel.org/r/20240327063143.2266464-2-Vijendar.Mukunda@amd.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
drivers/soundwire/amd_manager.c
drivers/soundwire/amd_manager.h

index 7cd24bd8e2248ef9c0e5fece95b3fb58e94f4e1e..6bcf8e75273c4e03cff5823dd77bc5ac38fd2360 100644 (file)
@@ -130,6 +130,19 @@ static void amd_sdw_set_frameshape(struct amd_sdw_manager *amd_manager)
        writel(frame_size, amd_manager->mmio + ACP_SW_FRAMESIZE);
 }
 
+static void amd_sdw_wake_enable(struct amd_sdw_manager *amd_manager, bool enable)
+{
+       u32 wake_ctrl;
+
+       wake_ctrl = readl(amd_manager->mmio + ACP_SW_STATE_CHANGE_STATUS_MASK_8TO11);
+       if (enable)
+               wake_ctrl |= AMD_SDW_WAKE_INTR_MASK;
+       else
+               wake_ctrl &= ~AMD_SDW_WAKE_INTR_MASK;
+
+       writel(wake_ctrl, amd_manager->mmio + ACP_SW_STATE_CHANGE_STATUS_MASK_8TO11);
+}
+
 static void amd_sdw_ctl_word_prep(u32 *lower_word, u32 *upper_word, struct sdw_msg *msg,
                                  int cmd_offset)
 {
@@ -1095,6 +1108,7 @@ static int __maybe_unused amd_suspend(struct device *dev)
        }
 
        if (amd_manager->power_mode_mask & AMD_SDW_CLK_STOP_MODE) {
+               amd_sdw_wake_enable(amd_manager, false);
                return amd_sdw_clock_stop(amd_manager);
        } else if (amd_manager->power_mode_mask & AMD_SDW_POWER_OFF_MODE) {
                /*
@@ -1121,6 +1135,7 @@ static int __maybe_unused amd_suspend_runtime(struct device *dev)
                return 0;
        }
        if (amd_manager->power_mode_mask & AMD_SDW_CLK_STOP_MODE) {
+               amd_sdw_wake_enable(amd_manager, true);
                return amd_sdw_clock_stop(amd_manager);
        } else if (amd_manager->power_mode_mask & AMD_SDW_POWER_OFF_MODE) {
                ret = amd_sdw_clock_stop(amd_manager);
index 418b679e0b1a684e0a3ac502d94f74d24d24c00d..707065468e05a038acb1a1c893133b5d757a4de8 100644 (file)
 #define AMD_SDW0_EXT_INTR_MASK         0x200000
 #define AMD_SDW1_EXT_INTR_MASK         4
 #define AMD_SDW_IRQ_MASK_0TO7          0x77777777
-#define AMD_SDW_IRQ_MASK_8TO11         0x000d7777
+#define AMD_SDW_IRQ_MASK_8TO11         0x000c7777
 #define AMD_SDW_IRQ_ERROR_MASK         0xff
 #define AMD_SDW_MAX_FREQ_NUM           1
 #define AMD_SDW0_MAX_TX_PORTS          3
 #define AMD_SDW_CLK_RESUME_REQ                         2
 #define AMD_SDW_CLK_RESUME_DONE                                3
 #define AMD_SDW_WAKE_STAT_MASK                         BIT(16)
+#define AMD_SDW_WAKE_INTR_MASK                         BIT(16)
 
 static u32 amd_sdw_freq_tbl[AMD_SDW_MAX_FREQ_NUM] = {
        AMD_SDW_DEFAULT_CLK_FREQ,