]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
ASoC: SOF: amd: add soundwire wake irq handling
authorVijendar Mukunda <Vijendar.Mukunda@amd.com>
Fri, 2 May 2025 15:42:47 +0000 (21:12 +0530)
committerMark Brown <broonie@kernel.org>
Fri, 2 May 2025 23:16:44 +0000 (08:16 +0900)
Add SoundWire wake interrupt handling for ACP7.0 & ACP7.1
platforms.

Signed-off-by: Vijendar Mukunda <Vijendar.Mukunda@amd.com>
Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Reviewed-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Link: https://patch.msgid.link/20250502154445.3008598-9-Vijendar.Mukunda@amd.com
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/sof/amd/acp-dsp-offset.h
sound/soc/sof/amd/acp.c
sound/soc/sof/amd/acp.h

index e77554f74c20db7970098b8fe3286f7d380e1f56..08583a91afbc47420250cca5e48dbe354d18d20c 100644 (file)
 #define ACP70_SW0_WAKE_EN                      0x1458
 #define ACP70_SW1_WAKE_EN                      0x1460
 #define ACP70_SDW_HOST_WAKE_MASK               0x0C00000
+#define ACP70_SDW0_HOST_WAKE_STAT              BIT(24)
+#define ACP70_SDW1_HOST_WAKE_STAT              BIT(25)
+#define ACP70_SDW0_PME_STAT                    BIT(26)
+#define ACP70_SDW1_PME_STAT                    BIT(27)
 
 #endif
index d62ba4f75e4fcc64a08b62b03abc685ee0841d2e..ec904482a294c7cec6dba952a5bb321c8d5a3eb0 100644 (file)
@@ -386,6 +386,69 @@ static int acp_memory_init(struct snd_sof_dev *sdev)
        return 0;
 }
 
+static void amd_sof_handle_acp70_sdw_wake_event(struct acp_dev_data *adata)
+{
+       struct amd_sdw_manager *amd_manager;
+
+       if (adata->acp70_sdw0_wake_event) {
+               amd_manager = dev_get_drvdata(&adata->sdw->pdev[0]->dev);
+               if (amd_manager)
+                       pm_request_resume(amd_manager->dev);
+               adata->acp70_sdw0_wake_event = 0;
+       }
+
+       if (adata->acp70_sdw1_wake_event) {
+               amd_manager = dev_get_drvdata(&adata->sdw->pdev[1]->dev);
+               if (amd_manager)
+                       pm_request_resume(amd_manager->dev);
+               adata->acp70_sdw1_wake_event = 0;
+       }
+}
+
+static int amd_sof_check_and_handle_acp70_sdw_wake_irq(struct snd_sof_dev *sdev)
+{
+       const struct sof_amd_acp_desc *desc = get_chip_info(sdev->pdata);
+       struct acp_dev_data *adata = sdev->pdata->hw_pdata;
+       u32 ext_intr_stat1;
+       int irq_flag = 0;
+       bool sdw_wake_irq = false;
+
+       ext_intr_stat1 = snd_sof_dsp_read(sdev, ACP_DSP_BAR, desc->ext_intr_stat1);
+       if (ext_intr_stat1 & ACP70_SDW0_HOST_WAKE_STAT) {
+               snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->ext_intr_stat1,
+                                 ACP70_SDW0_HOST_WAKE_STAT);
+               adata->acp70_sdw0_wake_event = true;
+               sdw_wake_irq = true;
+       }
+
+       if (ext_intr_stat1 & ACP70_SDW1_HOST_WAKE_STAT) {
+               snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->ext_intr_stat1,
+                                 ACP70_SDW1_HOST_WAKE_STAT);
+               adata->acp70_sdw1_wake_event = true;
+               sdw_wake_irq = true;
+       }
+
+       if (ext_intr_stat1 & ACP70_SDW0_PME_STAT) {
+               snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP70_SW0_WAKE_EN, 0);
+               snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->ext_intr_stat1, ACP70_SDW0_PME_STAT);
+               adata->acp70_sdw0_wake_event = true;
+               sdw_wake_irq = true;
+       }
+
+       if (ext_intr_stat1 & ACP70_SDW1_PME_STAT) {
+               snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP70_SW1_WAKE_EN, 0);
+               snd_sof_dsp_write(sdev, ACP_DSP_BAR, desc->ext_intr_stat1, ACP70_SDW1_PME_STAT);
+               adata->acp70_sdw1_wake_event = true;
+               sdw_wake_irq = true;
+       }
+
+       if (sdw_wake_irq) {
+               amd_sof_handle_acp70_sdw_wake_event(adata);
+               irq_flag = 1;
+       }
+       return irq_flag;
+}
+
 static irqreturn_t acp_irq_thread(int irq, void *context)
 {
        struct snd_sof_dev *sdev = context;
@@ -418,7 +481,7 @@ static irqreturn_t acp_irq_handler(int irq, void *dev_id)
        struct acp_dev_data *adata = sdev->pdata->hw_pdata;
        unsigned int base = desc->dsp_intr_base;
        unsigned int val;
-       int irq_flag = 0;
+       int irq_flag = 0, wake_irq_flag = 0;
 
        val = snd_sof_dsp_read(sdev, ACP_DSP_BAR, base + DSP_SW_INTR_STAT_OFFSET);
        if (val & ACP_DSP_TO_HOST_IRQ) {
@@ -456,8 +519,14 @@ static irqreturn_t acp_irq_handler(int irq, void *dev_id)
                                schedule_work(&amd_manager->amd_sdw_irq_thread);
                        irq_flag = 1;
                }
+               switch (adata->pci_rev) {
+               case ACP70_PCI_ID:
+               case ACP71_PCI_ID:
+                       wake_irq_flag = amd_sof_check_and_handle_acp70_sdw_wake_irq(sdev);
+                       break;
+               }
        }
-       if (irq_flag)
+       if (irq_flag || wake_irq_flag)
                return IRQ_HANDLED;
        else
                return IRQ_NONE;
index 097454f2b48bfbb522c05287ff0502b6b574f9f1..d3c5b2386cdf589caaa0bbb5175e8a238fcebc55 100644 (file)
@@ -263,6 +263,10 @@ struct acp_dev_data {
        bool is_dram_in_use;
        bool is_sram_in_use;
        bool sdw_en_stat;
+       /* acp70_sdw0_wake_event flag set to true when wake irq asserted for SW0 instance */
+       bool acp70_sdw0_wake_event;
+       /* acp70_sdw1_wake_event flag set to true when wake irq asserted for SW1 instance */
+       bool acp70_sdw1_wake_event;
        unsigned int pci_rev;
 };