ASoC: amd: ps: add soundwire wake interrupt handling

Add SoundWire wake interrupt handling for ACP7.0 & ACP7.1 platforms.

Signed-off-by: Vijendar Mukunda <Vijendar.Mukunda@amd.com>
Link: https://patch.msgid.link/20250207062819.1527184-18-Vijendar.Mukunda@amd.com
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Vijendar Mukunda 2025-02-07 11:58:11 +05:30 committed by Mark Brown
parent 0b6914a012
commit 3898b18907
No known key found for this signature in database
GPG key ID: 24D68B725D5487D0
2 changed files with 70 additions and 0 deletions

View file

@ -139,6 +139,10 @@
#define ACP70_PGFSM_STATUS_MASK 0xFF #define ACP70_PGFSM_STATUS_MASK 0xFF
#define ACP70_TIMEOUT 2000 #define ACP70_TIMEOUT 2000
#define ACP70_SDW_HOST_WAKE_MASK 0x0C00000 #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)
#define ACP70_SDW0_DMA_MAX_STREAMS 6 #define ACP70_SDW0_DMA_MAX_STREAMS 6
#define ACP70_SDW1_DMA_MAX_STREAMS ACP70_SDW0_DMA_MAX_STREAMS #define ACP70_SDW1_DMA_MAX_STREAMS ACP70_SDW0_DMA_MAX_STREAMS
@ -325,6 +329,8 @@ struct acp_hw_ops {
* @is_pdm_config: flat set to true when PDM configuration is selected from BIOS * @is_pdm_config: flat set to true when PDM configuration is selected from BIOS
* @is_sdw_config: flag set to true when SDW configuration is selected from BIOS * @is_sdw_config: flag set to true when SDW configuration is selected from BIOS
* @sdw_en_stat: flag set to true when any one of the SoundWire manager instance is enabled * @sdw_en_stat: flag set to true when any one of the SoundWire manager instance is enabled
* @acp70_sdw0_wake_event: flag set to true when wake irq asserted for SW0 instance
* @acp70_sdw1_wake_event: flag set to true when wake irq asserted for SW1 instance
* @addr: pci ioremap address * @addr: pci ioremap address
* @reg_range: ACP reigister range * @reg_range: ACP reigister range
* @acp_rev: ACP PCI revision id * @acp_rev: ACP PCI revision id
@ -356,6 +362,8 @@ struct acp63_dev_data {
bool is_pdm_config; bool is_pdm_config;
bool is_sdw_config; bool is_sdw_config;
bool sdw_en_stat; bool sdw_en_stat;
bool acp70_sdw0_wake_event;
bool acp70_sdw1_wake_event;
u32 addr; u32 addr;
u32 reg_range; u32 reg_range;
u32 acp_rev; u32 acp_rev;

View file

@ -21,6 +21,65 @@
#include "acp63.h" #include "acp63.h"
static void handle_acp70_sdw_wake_event(struct acp63_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 short int check_and_handle_acp70_sdw_wake_irq(struct acp63_dev_data *adata)
{
u32 ext_intr_stat1;
int irq_flag = 0;
bool sdw_wake_irq = false;
ext_intr_stat1 = readl(adata->acp63_base + ACP_EXTERNAL_INTR_STAT1);
if (ext_intr_stat1 & ACP70_SDW0_HOST_WAKE_STAT) {
writel(ACP70_SDW0_HOST_WAKE_STAT, adata->acp63_base + ACP_EXTERNAL_INTR_STAT1);
adata->acp70_sdw0_wake_event = true;
sdw_wake_irq = true;
}
if (ext_intr_stat1 & ACP70_SDW1_HOST_WAKE_STAT) {
writel(ACP70_SDW1_HOST_WAKE_STAT, adata->acp63_base + ACP_EXTERNAL_INTR_STAT1);
adata->acp70_sdw1_wake_event = true;
sdw_wake_irq = true;
}
if (ext_intr_stat1 & ACP70_SDW0_PME_STAT) {
writel(0, adata->acp63_base + ACP_SW0_WAKE_EN);
writel(ACP70_SDW0_PME_STAT, adata->acp63_base + ACP_EXTERNAL_INTR_STAT1);
adata->acp70_sdw0_wake_event = true;
sdw_wake_irq = true;
}
if (ext_intr_stat1 & ACP70_SDW1_PME_STAT) {
writel(0, adata->acp63_base + ACP_SW1_WAKE_EN);
writel(ACP70_SDW1_PME_STAT, adata->acp63_base + ACP_EXTERNAL_INTR_STAT1);
adata->acp70_sdw1_wake_event = true;
sdw_wake_irq = true;
}
if (sdw_wake_irq) {
handle_acp70_sdw_wake_event(adata);
irq_flag = 1;
}
return irq_flag;
}
static short int check_and_handle_sdw_dma_irq(struct acp63_dev_data *adata, u32 ext_intr_stat, static short int check_and_handle_sdw_dma_irq(struct acp63_dev_data *adata, u32 ext_intr_stat,
u32 ext_intr_stat1) u32 ext_intr_stat1)
{ {
@ -163,6 +222,9 @@ static irqreturn_t acp63_irq_handler(int irq, void *dev_id)
irq_flag = 1; irq_flag = 1;
} }
if (adata->acp_rev >= ACP70_PCI_REV)
irq_flag = check_and_handle_acp70_sdw_wake_irq(adata);
if (ext_intr_stat & BIT(PDM_DMA_STAT)) { if (ext_intr_stat & BIT(PDM_DMA_STAT)) {
ps_pdm_data = dev_get_drvdata(&adata->pdm_dev->dev); ps_pdm_data = dev_get_drvdata(&adata->pdm_dev->dev);
writel(BIT(PDM_DMA_STAT), adata->acp63_base + ACP_EXTERNAL_INTR_STAT); writel(BIT(PDM_DMA_STAT), adata->acp63_base + ACP_EXTERNAL_INTR_STAT);