1db746fffSVijendar Mukunda // SPDX-License-Identifier: GPL-2.0-only
2db746fffSVijendar Mukunda /*
3db746fffSVijendar Mukunda * AMD ACP PCI driver callback routines for ACP6.3, ACP7.0 & ACP7.1
4db746fffSVijendar Mukunda * platforms.
5db746fffSVijendar Mukunda *
6db746fffSVijendar Mukunda * Copyright 2025 Advanced Micro Devices, Inc.
7db746fffSVijendar Mukunda * Authors: Vijendar Mukunda <Vijendar.Mukunda@amd.com>
8db746fffSVijendar Mukunda */
9db746fffSVijendar Mukunda
10db746fffSVijendar Mukunda #include <linux/bitops.h>
11db746fffSVijendar Mukunda #include <linux/delay.h>
12db746fffSVijendar Mukunda #include <linux/export.h>
13db746fffSVijendar Mukunda #include <linux/io.h>
14db746fffSVijendar Mukunda #include <linux/iopoll.h>
156547577eSVijendar Mukunda #include <linux/pci.h>
16db746fffSVijendar Mukunda #include <linux/platform_device.h>
1749162838SVijendar Mukunda #include <linux/pm_runtime.h>
180a27b2d7SVijendar Mukunda #include <sound/pcm_params.h>
19db746fffSVijendar Mukunda
20db746fffSVijendar Mukunda #include "acp63.h"
21db746fffSVijendar Mukunda
acp63_power_on(void __iomem * acp_base)22db746fffSVijendar Mukunda static int acp63_power_on(void __iomem *acp_base)
23db746fffSVijendar Mukunda {
24db746fffSVijendar Mukunda u32 val;
25db746fffSVijendar Mukunda
26db746fffSVijendar Mukunda val = readl(acp_base + ACP_PGFSM_STATUS);
27db746fffSVijendar Mukunda
28db746fffSVijendar Mukunda if (!val)
29db746fffSVijendar Mukunda return val;
30db746fffSVijendar Mukunda
31db746fffSVijendar Mukunda if ((val & ACP63_PGFSM_STATUS_MASK) != ACP63_POWER_ON_IN_PROGRESS)
32db746fffSVijendar Mukunda writel(ACP63_PGFSM_CNTL_POWER_ON_MASK, acp_base + ACP_PGFSM_CONTROL);
33db746fffSVijendar Mukunda
34db746fffSVijendar Mukunda return readl_poll_timeout(acp_base + ACP_PGFSM_STATUS, val, !val, DELAY_US, ACP63_TIMEOUT);
35db746fffSVijendar Mukunda }
36db746fffSVijendar Mukunda
acp63_reset(void __iomem * acp_base)37db746fffSVijendar Mukunda static int acp63_reset(void __iomem *acp_base)
38db746fffSVijendar Mukunda {
39db746fffSVijendar Mukunda u32 val;
40db746fffSVijendar Mukunda int ret;
41db746fffSVijendar Mukunda
42db746fffSVijendar Mukunda writel(1, acp_base + ACP_SOFT_RESET);
43db746fffSVijendar Mukunda
44db746fffSVijendar Mukunda ret = readl_poll_timeout(acp_base + ACP_SOFT_RESET, val,
45db746fffSVijendar Mukunda val & ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK,
46db746fffSVijendar Mukunda DELAY_US, ACP63_TIMEOUT);
47db746fffSVijendar Mukunda if (ret)
48db746fffSVijendar Mukunda return ret;
49db746fffSVijendar Mukunda
50db746fffSVijendar Mukunda writel(0, acp_base + ACP_SOFT_RESET);
51db746fffSVijendar Mukunda
52db746fffSVijendar Mukunda return readl_poll_timeout(acp_base + ACP_SOFT_RESET, val, !val, DELAY_US, ACP63_TIMEOUT);
53db746fffSVijendar Mukunda }
54db746fffSVijendar Mukunda
acp63_enable_interrupts(void __iomem * acp_base)55db746fffSVijendar Mukunda static void acp63_enable_interrupts(void __iomem *acp_base)
56db746fffSVijendar Mukunda {
57db746fffSVijendar Mukunda writel(1, acp_base + ACP_EXTERNAL_INTR_ENB);
58db746fffSVijendar Mukunda writel(ACP_ERROR_IRQ, acp_base + ACP_EXTERNAL_INTR_CNTL);
59db746fffSVijendar Mukunda }
60db746fffSVijendar Mukunda
acp63_disable_interrupts(void __iomem * acp_base)61db746fffSVijendar Mukunda static void acp63_disable_interrupts(void __iomem *acp_base)
62db746fffSVijendar Mukunda {
63db746fffSVijendar Mukunda writel(ACP_EXT_INTR_STAT_CLEAR_MASK, acp_base + ACP_EXTERNAL_INTR_STAT);
64db746fffSVijendar Mukunda writel(0, acp_base + ACP_EXTERNAL_INTR_CNTL);
65db746fffSVijendar Mukunda writel(0, acp_base + ACP_EXTERNAL_INTR_ENB);
66db746fffSVijendar Mukunda }
67db746fffSVijendar Mukunda
acp63_init(void __iomem * acp_base,struct device * dev)68db746fffSVijendar Mukunda static int acp63_init(void __iomem *acp_base, struct device *dev)
69db746fffSVijendar Mukunda {
70db746fffSVijendar Mukunda int ret;
71db746fffSVijendar Mukunda
72db746fffSVijendar Mukunda ret = acp63_power_on(acp_base);
73db746fffSVijendar Mukunda if (ret) {
74db746fffSVijendar Mukunda dev_err(dev, "ACP power on failed\n");
75db746fffSVijendar Mukunda return ret;
76db746fffSVijendar Mukunda }
77db746fffSVijendar Mukunda writel(0x01, acp_base + ACP_CONTROL);
78db746fffSVijendar Mukunda ret = acp63_reset(acp_base);
79db746fffSVijendar Mukunda if (ret) {
80db746fffSVijendar Mukunda dev_err(dev, "ACP reset failed\n");
81db746fffSVijendar Mukunda return ret;
82db746fffSVijendar Mukunda }
83db746fffSVijendar Mukunda acp63_enable_interrupts(acp_base);
84db746fffSVijendar Mukunda writel(0, acp_base + ACP_ZSC_DSP_CTRL);
85db746fffSVijendar Mukunda return 0;
86db746fffSVijendar Mukunda }
87db746fffSVijendar Mukunda
acp63_deinit(void __iomem * acp_base,struct device * dev)88db746fffSVijendar Mukunda static int acp63_deinit(void __iomem *acp_base, struct device *dev)
89db746fffSVijendar Mukunda {
90db746fffSVijendar Mukunda int ret;
91db746fffSVijendar Mukunda
92db746fffSVijendar Mukunda acp63_disable_interrupts(acp_base);
93db746fffSVijendar Mukunda ret = acp63_reset(acp_base);
94db746fffSVijendar Mukunda if (ret) {
95db746fffSVijendar Mukunda dev_err(dev, "ACP reset failed\n");
96db746fffSVijendar Mukunda return ret;
97db746fffSVijendar Mukunda }
98db746fffSVijendar Mukunda writel(0, acp_base + ACP_CONTROL);
99db746fffSVijendar Mukunda writel(1, acp_base + ACP_ZSC_DSP_CTRL);
100db746fffSVijendar Mukunda return 0;
101db746fffSVijendar Mukunda }
102db746fffSVijendar Mukunda
acp63_get_config(struct pci_dev * pci,struct acp63_dev_data * acp_data)1036547577eSVijendar Mukunda static void acp63_get_config(struct pci_dev *pci, struct acp63_dev_data *acp_data)
1046547577eSVijendar Mukunda {
1056547577eSVijendar Mukunda u32 config;
1066547577eSVijendar Mukunda
1076547577eSVijendar Mukunda config = readl(acp_data->acp63_base + ACP_PIN_CONFIG);
1086547577eSVijendar Mukunda dev_dbg(&pci->dev, "ACP config value: %d\n", config);
1096547577eSVijendar Mukunda switch (config) {
1106547577eSVijendar Mukunda case ACP_CONFIG_4:
1116547577eSVijendar Mukunda case ACP_CONFIG_5:
1126547577eSVijendar Mukunda case ACP_CONFIG_10:
1136547577eSVijendar Mukunda case ACP_CONFIG_11:
1146547577eSVijendar Mukunda acp_data->is_pdm_config = true;
1156547577eSVijendar Mukunda break;
1166547577eSVijendar Mukunda case ACP_CONFIG_2:
1176547577eSVijendar Mukunda case ACP_CONFIG_3:
1186547577eSVijendar Mukunda acp_data->is_sdw_config = true;
1196547577eSVijendar Mukunda break;
1206547577eSVijendar Mukunda case ACP_CONFIG_6:
1216547577eSVijendar Mukunda case ACP_CONFIG_7:
1226547577eSVijendar Mukunda case ACP_CONFIG_12:
1236547577eSVijendar Mukunda case ACP_CONFIG_8:
1246547577eSVijendar Mukunda case ACP_CONFIG_13:
1256547577eSVijendar Mukunda case ACP_CONFIG_14:
1266547577eSVijendar Mukunda acp_data->is_pdm_config = true;
1276547577eSVijendar Mukunda acp_data->is_sdw_config = true;
1286547577eSVijendar Mukunda break;
1296547577eSVijendar Mukunda default:
1306547577eSVijendar Mukunda break;
1316547577eSVijendar Mukunda }
1326547577eSVijendar Mukunda }
1336547577eSVijendar Mukunda
check_acp_sdw_enable_status(struct acp63_dev_data * adata)13449162838SVijendar Mukunda static bool check_acp_sdw_enable_status(struct acp63_dev_data *adata)
13549162838SVijendar Mukunda {
13649162838SVijendar Mukunda u32 sdw0_en, sdw1_en;
13749162838SVijendar Mukunda
13849162838SVijendar Mukunda sdw0_en = readl(adata->acp63_base + ACP_SW0_EN);
13949162838SVijendar Mukunda sdw1_en = readl(adata->acp63_base + ACP_SW1_EN);
14049162838SVijendar Mukunda return (sdw0_en || sdw1_en);
14149162838SVijendar Mukunda }
14249162838SVijendar Mukunda
handle_acp63_sdw_pme_event(struct acp63_dev_data * adata)14349162838SVijendar Mukunda static void handle_acp63_sdw_pme_event(struct acp63_dev_data *adata)
14449162838SVijendar Mukunda {
14549162838SVijendar Mukunda u32 val;
14649162838SVijendar Mukunda
14749162838SVijendar Mukunda val = readl(adata->acp63_base + ACP_SW0_WAKE_EN);
14849162838SVijendar Mukunda if (val && adata->sdw->pdev[0])
14949162838SVijendar Mukunda pm_request_resume(&adata->sdw->pdev[0]->dev);
15049162838SVijendar Mukunda
15149162838SVijendar Mukunda val = readl(adata->acp63_base + ACP_SW1_WAKE_EN);
15249162838SVijendar Mukunda if (val && adata->sdw->pdev[1])
15349162838SVijendar Mukunda pm_request_resume(&adata->sdw->pdev[1]->dev);
15449162838SVijendar Mukunda }
15549162838SVijendar Mukunda
snd_acp63_suspend(struct device * dev)15649162838SVijendar Mukunda static int __maybe_unused snd_acp63_suspend(struct device *dev)
15749162838SVijendar Mukunda {
15849162838SVijendar Mukunda struct acp63_dev_data *adata;
15949162838SVijendar Mukunda int ret;
16049162838SVijendar Mukunda
16149162838SVijendar Mukunda adata = dev_get_drvdata(dev);
16249162838SVijendar Mukunda if (adata->is_sdw_dev) {
163*dc6458edSVijendar Mukunda adata->acp_sw_pad_keeper_en = readl(adata->acp63_base + ACP_SW0_PAD_KEEPER_EN);
164*dc6458edSVijendar Mukunda adata->acp_pad_pulldown_ctrl = readl(adata->acp63_base + ACP_PAD_PULLDOWN_CTRL);
16549162838SVijendar Mukunda adata->sdw_en_stat = check_acp_sdw_enable_status(adata);
16649162838SVijendar Mukunda if (adata->sdw_en_stat) {
16749162838SVijendar Mukunda writel(1, adata->acp63_base + ACP_ZSC_DSP_CTRL);
16849162838SVijendar Mukunda return 0;
16949162838SVijendar Mukunda }
17049162838SVijendar Mukunda }
17149162838SVijendar Mukunda ret = acp_hw_deinit(adata, dev);
17249162838SVijendar Mukunda if (ret)
17349162838SVijendar Mukunda dev_err(dev, "ACP de-init failed\n");
17449162838SVijendar Mukunda
17549162838SVijendar Mukunda return ret;
17649162838SVijendar Mukunda }
17749162838SVijendar Mukunda
snd_acp63_runtime_resume(struct device * dev)17849162838SVijendar Mukunda static int __maybe_unused snd_acp63_runtime_resume(struct device *dev)
17949162838SVijendar Mukunda {
18049162838SVijendar Mukunda struct acp63_dev_data *adata;
18149162838SVijendar Mukunda int ret;
18249162838SVijendar Mukunda
18349162838SVijendar Mukunda adata = dev_get_drvdata(dev);
18449162838SVijendar Mukunda if (adata->sdw_en_stat) {
18549162838SVijendar Mukunda writel(0, adata->acp63_base + ACP_ZSC_DSP_CTRL);
18649162838SVijendar Mukunda return 0;
18749162838SVijendar Mukunda }
18849162838SVijendar Mukunda ret = acp_hw_init(adata, dev);
18949162838SVijendar Mukunda if (ret) {
19049162838SVijendar Mukunda dev_err(dev, "ACP init failed\n");
19149162838SVijendar Mukunda return ret;
19249162838SVijendar Mukunda }
19349162838SVijendar Mukunda
19449162838SVijendar Mukunda if (!adata->sdw_en_stat)
19549162838SVijendar Mukunda handle_acp63_sdw_pme_event(adata);
19649162838SVijendar Mukunda return 0;
19749162838SVijendar Mukunda }
19849162838SVijendar Mukunda
snd_acp63_resume(struct device * dev)19949162838SVijendar Mukunda static int __maybe_unused snd_acp63_resume(struct device *dev)
20049162838SVijendar Mukunda {
20149162838SVijendar Mukunda struct acp63_dev_data *adata;
202*dc6458edSVijendar Mukunda u32 acp_sw_pad_keeper_en;
20349162838SVijendar Mukunda int ret;
20449162838SVijendar Mukunda
20549162838SVijendar Mukunda adata = dev_get_drvdata(dev);
20649162838SVijendar Mukunda if (adata->sdw_en_stat) {
20749162838SVijendar Mukunda writel(0, adata->acp63_base + ACP_ZSC_DSP_CTRL);
20849162838SVijendar Mukunda return 0;
20949162838SVijendar Mukunda }
21049162838SVijendar Mukunda
21149162838SVijendar Mukunda ret = acp_hw_init(adata, dev);
21249162838SVijendar Mukunda if (ret)
21349162838SVijendar Mukunda dev_err(dev, "ACP init failed\n");
21449162838SVijendar Mukunda
215*dc6458edSVijendar Mukunda acp_sw_pad_keeper_en = readl(adata->acp63_base + ACP_SW0_PAD_KEEPER_EN);
216*dc6458edSVijendar Mukunda dev_dbg(dev, "ACP_SW0_PAD_KEEPER_EN:0x%x\n", acp_sw_pad_keeper_en);
217*dc6458edSVijendar Mukunda if (!acp_sw_pad_keeper_en) {
218*dc6458edSVijendar Mukunda writel(adata->acp_sw_pad_keeper_en, adata->acp63_base + ACP_SW0_PAD_KEEPER_EN);
219*dc6458edSVijendar Mukunda writel(adata->acp_pad_pulldown_ctrl, adata->acp63_base + ACP_PAD_PULLDOWN_CTRL);
220*dc6458edSVijendar Mukunda }
22149162838SVijendar Mukunda return ret;
22249162838SVijendar Mukunda }
22349162838SVijendar Mukunda
acp63_sdw_dma_irq_thread(struct acp63_dev_data * adata)2240a27b2d7SVijendar Mukunda static void acp63_sdw_dma_irq_thread(struct acp63_dev_data *adata)
2250a27b2d7SVijendar Mukunda {
2260a27b2d7SVijendar Mukunda struct sdw_dma_dev_data *sdw_data;
2270a27b2d7SVijendar Mukunda u32 stream_id;
2280a27b2d7SVijendar Mukunda
2290a27b2d7SVijendar Mukunda sdw_data = dev_get_drvdata(&adata->sdw_dma_dev->dev);
2300a27b2d7SVijendar Mukunda
2310a27b2d7SVijendar Mukunda for (stream_id = 0; stream_id < ACP63_SDW0_DMA_MAX_STREAMS; stream_id++) {
2320a27b2d7SVijendar Mukunda if (adata->acp63_sdw0_dma_intr_stat[stream_id]) {
2330a27b2d7SVijendar Mukunda if (sdw_data->acp63_sdw0_dma_stream[stream_id])
2340a27b2d7SVijendar Mukunda snd_pcm_period_elapsed(sdw_data->acp63_sdw0_dma_stream[stream_id]);
2350a27b2d7SVijendar Mukunda adata->acp63_sdw0_dma_intr_stat[stream_id] = 0;
2360a27b2d7SVijendar Mukunda }
2370a27b2d7SVijendar Mukunda }
2380a27b2d7SVijendar Mukunda for (stream_id = 0; stream_id < ACP63_SDW1_DMA_MAX_STREAMS; stream_id++) {
2390a27b2d7SVijendar Mukunda if (adata->acp63_sdw1_dma_intr_stat[stream_id]) {
2400a27b2d7SVijendar Mukunda if (sdw_data->acp63_sdw1_dma_stream[stream_id])
2410a27b2d7SVijendar Mukunda snd_pcm_period_elapsed(sdw_data->acp63_sdw1_dma_stream[stream_id]);
2420a27b2d7SVijendar Mukunda adata->acp63_sdw1_dma_intr_stat[stream_id] = 0;
2430a27b2d7SVijendar Mukunda }
2440a27b2d7SVijendar Mukunda }
2450a27b2d7SVijendar Mukunda }
2460a27b2d7SVijendar Mukunda
acp63_hw_init_ops(struct acp_hw_ops * hw_ops)247db746fffSVijendar Mukunda void acp63_hw_init_ops(struct acp_hw_ops *hw_ops)
248db746fffSVijendar Mukunda {
249db746fffSVijendar Mukunda hw_ops->acp_init = acp63_init;
250db746fffSVijendar Mukunda hw_ops->acp_deinit = acp63_deinit;
2516547577eSVijendar Mukunda hw_ops->acp_get_config = acp63_get_config;
2520a27b2d7SVijendar Mukunda hw_ops->acp_sdw_dma_irq_thread = acp63_sdw_dma_irq_thread;
25349162838SVijendar Mukunda hw_ops->acp_suspend = snd_acp63_suspend;
25449162838SVijendar Mukunda hw_ops->acp_resume = snd_acp63_resume;
25549162838SVijendar Mukunda hw_ops->acp_suspend_runtime = snd_acp63_suspend;
25649162838SVijendar Mukunda hw_ops->acp_resume_runtime = snd_acp63_runtime_resume;
257db746fffSVijendar Mukunda }
2587c0ea26cSVijendar Mukunda
acp70_power_on(void __iomem * acp_base)2597c0ea26cSVijendar Mukunda static int acp70_power_on(void __iomem *acp_base)
2607c0ea26cSVijendar Mukunda {
2617c0ea26cSVijendar Mukunda u32 val = 0;
2627c0ea26cSVijendar Mukunda
2637c0ea26cSVijendar Mukunda val = readl(acp_base + ACP_PGFSM_STATUS);
2647c0ea26cSVijendar Mukunda
2657c0ea26cSVijendar Mukunda if (!val)
2667c0ea26cSVijendar Mukunda return 0;
2677c0ea26cSVijendar Mukunda if (val & ACP70_PGFSM_STATUS_MASK)
2687c0ea26cSVijendar Mukunda writel(ACP70_PGFSM_CNTL_POWER_ON_MASK, acp_base + ACP_PGFSM_CONTROL);
2697c0ea26cSVijendar Mukunda
2707c0ea26cSVijendar Mukunda return readl_poll_timeout(acp_base + ACP_PGFSM_STATUS, val, !val, DELAY_US, ACP70_TIMEOUT);
2717c0ea26cSVijendar Mukunda }
2727c0ea26cSVijendar Mukunda
acp70_reset(void __iomem * acp_base)2737c0ea26cSVijendar Mukunda static int acp70_reset(void __iomem *acp_base)
2747c0ea26cSVijendar Mukunda {
2757c0ea26cSVijendar Mukunda u32 val;
2767c0ea26cSVijendar Mukunda int ret;
2777c0ea26cSVijendar Mukunda
2787c0ea26cSVijendar Mukunda writel(1, acp_base + ACP_SOFT_RESET);
2797c0ea26cSVijendar Mukunda
2807c0ea26cSVijendar Mukunda ret = readl_poll_timeout(acp_base + ACP_SOFT_RESET, val,
2817c0ea26cSVijendar Mukunda val & ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK,
2827c0ea26cSVijendar Mukunda DELAY_US, ACP70_TIMEOUT);
2837c0ea26cSVijendar Mukunda if (ret)
2847c0ea26cSVijendar Mukunda return ret;
2857c0ea26cSVijendar Mukunda
2867c0ea26cSVijendar Mukunda writel(0, acp_base + ACP_SOFT_RESET);
2877c0ea26cSVijendar Mukunda
2887c0ea26cSVijendar Mukunda return readl_poll_timeout(acp_base + ACP_SOFT_RESET, val, !val, DELAY_US, ACP70_TIMEOUT);
2897c0ea26cSVijendar Mukunda }
2907c0ea26cSVijendar Mukunda
acp70_enable_sdw_host_wake_interrupts(void __iomem * acp_base)2917c0ea26cSVijendar Mukunda static void acp70_enable_sdw_host_wake_interrupts(void __iomem *acp_base)
2927c0ea26cSVijendar Mukunda {
2937c0ea26cSVijendar Mukunda u32 ext_intr_cntl1;
2947c0ea26cSVijendar Mukunda
2957c0ea26cSVijendar Mukunda ext_intr_cntl1 = readl(acp_base + ACP_EXTERNAL_INTR_CNTL1);
2967c0ea26cSVijendar Mukunda ext_intr_cntl1 |= ACP70_SDW_HOST_WAKE_MASK;
2977c0ea26cSVijendar Mukunda writel(ext_intr_cntl1, acp_base + ACP_EXTERNAL_INTR_CNTL1);
2987c0ea26cSVijendar Mukunda }
2997c0ea26cSVijendar Mukunda
acp70_enable_interrupts(void __iomem * acp_base)3007c0ea26cSVijendar Mukunda static void acp70_enable_interrupts(void __iomem *acp_base)
3017c0ea26cSVijendar Mukunda {
3027c0ea26cSVijendar Mukunda u32 sdw0_wake_en, sdw1_wake_en;
3037c0ea26cSVijendar Mukunda
3047c0ea26cSVijendar Mukunda writel(1, acp_base + ACP_EXTERNAL_INTR_ENB);
3057c0ea26cSVijendar Mukunda writel(ACP_ERROR_IRQ, acp_base + ACP_EXTERNAL_INTR_CNTL);
3067c0ea26cSVijendar Mukunda sdw0_wake_en = readl(acp_base + ACP_SW0_WAKE_EN);
3077c0ea26cSVijendar Mukunda sdw1_wake_en = readl(acp_base + ACP_SW1_WAKE_EN);
3087c0ea26cSVijendar Mukunda if (sdw0_wake_en || sdw1_wake_en)
3097c0ea26cSVijendar Mukunda acp70_enable_sdw_host_wake_interrupts(acp_base);
3107c0ea26cSVijendar Mukunda }
3117c0ea26cSVijendar Mukunda
acp70_disable_interrupts(void __iomem * acp_base)3127c0ea26cSVijendar Mukunda static void acp70_disable_interrupts(void __iomem *acp_base)
3137c0ea26cSVijendar Mukunda {
3147c0ea26cSVijendar Mukunda writel(ACP_EXT_INTR_STAT_CLEAR_MASK, acp_base + ACP_EXTERNAL_INTR_STAT);
3157c0ea26cSVijendar Mukunda writel(0, acp_base + ACP_EXTERNAL_INTR_CNTL);
3167c0ea26cSVijendar Mukunda writel(0, acp_base + ACP_EXTERNAL_INTR_ENB);
3177c0ea26cSVijendar Mukunda }
3187c0ea26cSVijendar Mukunda
acp70_init(void __iomem * acp_base,struct device * dev)3197c0ea26cSVijendar Mukunda static int acp70_init(void __iomem *acp_base, struct device *dev)
3207c0ea26cSVijendar Mukunda {
3217c0ea26cSVijendar Mukunda int ret;
3227c0ea26cSVijendar Mukunda
3237c0ea26cSVijendar Mukunda ret = acp70_power_on(acp_base);
3247c0ea26cSVijendar Mukunda if (ret) {
3257c0ea26cSVijendar Mukunda dev_err(dev, "ACP power on failed\n");
3267c0ea26cSVijendar Mukunda return ret;
3277c0ea26cSVijendar Mukunda }
3287c0ea26cSVijendar Mukunda writel(0x01, acp_base + ACP_CONTROL);
3297c0ea26cSVijendar Mukunda ret = acp70_reset(acp_base);
3307c0ea26cSVijendar Mukunda if (ret) {
3317c0ea26cSVijendar Mukunda dev_err(dev, "ACP reset failed\n");
3327c0ea26cSVijendar Mukunda return ret;
3337c0ea26cSVijendar Mukunda }
3347c0ea26cSVijendar Mukunda writel(0, acp_base + ACP_ZSC_DSP_CTRL);
3357c0ea26cSVijendar Mukunda acp70_enable_interrupts(acp_base);
3367c0ea26cSVijendar Mukunda writel(0x1, acp_base + ACP_PME_EN);
3377c0ea26cSVijendar Mukunda return 0;
3387c0ea26cSVijendar Mukunda }
3397c0ea26cSVijendar Mukunda
acp70_deinit(void __iomem * acp_base,struct device * dev)3407c0ea26cSVijendar Mukunda static int acp70_deinit(void __iomem *acp_base, struct device *dev)
3417c0ea26cSVijendar Mukunda {
3427c0ea26cSVijendar Mukunda int ret;
3437c0ea26cSVijendar Mukunda
3447c0ea26cSVijendar Mukunda acp70_disable_interrupts(acp_base);
3457c0ea26cSVijendar Mukunda ret = acp70_reset(acp_base);
3467c0ea26cSVijendar Mukunda if (ret) {
3477c0ea26cSVijendar Mukunda dev_err(dev, "ACP reset failed\n");
3487c0ea26cSVijendar Mukunda return ret;
3497c0ea26cSVijendar Mukunda }
3507c0ea26cSVijendar Mukunda writel(0x01, acp_base + ACP_ZSC_DSP_CTRL);
3517c0ea26cSVijendar Mukunda return 0;
3527c0ea26cSVijendar Mukunda }
3537c0ea26cSVijendar Mukunda
acp70_get_config(struct pci_dev * pci,struct acp63_dev_data * acp_data)3547c0ea26cSVijendar Mukunda static void acp70_get_config(struct pci_dev *pci, struct acp63_dev_data *acp_data)
3557c0ea26cSVijendar Mukunda {
3567c0ea26cSVijendar Mukunda u32 config;
3577c0ea26cSVijendar Mukunda
3587c0ea26cSVijendar Mukunda config = readl(acp_data->acp63_base + ACP_PIN_CONFIG);
3597c0ea26cSVijendar Mukunda dev_dbg(&pci->dev, "ACP config value: %d\n", config);
3607c0ea26cSVijendar Mukunda switch (config) {
3617c0ea26cSVijendar Mukunda case ACP_CONFIG_4:
3627c0ea26cSVijendar Mukunda case ACP_CONFIG_5:
3637c0ea26cSVijendar Mukunda case ACP_CONFIG_10:
3647c0ea26cSVijendar Mukunda case ACP_CONFIG_11:
3657c0ea26cSVijendar Mukunda case ACP_CONFIG_20:
3667c0ea26cSVijendar Mukunda acp_data->is_pdm_config = true;
3677c0ea26cSVijendar Mukunda break;
3687c0ea26cSVijendar Mukunda case ACP_CONFIG_2:
3697c0ea26cSVijendar Mukunda case ACP_CONFIG_3:
3707c0ea26cSVijendar Mukunda case ACP_CONFIG_16:
3717c0ea26cSVijendar Mukunda acp_data->is_sdw_config = true;
3727c0ea26cSVijendar Mukunda break;
3737c0ea26cSVijendar Mukunda case ACP_CONFIG_6:
3747c0ea26cSVijendar Mukunda case ACP_CONFIG_7:
3757c0ea26cSVijendar Mukunda case ACP_CONFIG_12:
3767c0ea26cSVijendar Mukunda case ACP_CONFIG_8:
3777c0ea26cSVijendar Mukunda case ACP_CONFIG_13:
3787c0ea26cSVijendar Mukunda case ACP_CONFIG_14:
3797c0ea26cSVijendar Mukunda case ACP_CONFIG_17:
3807c0ea26cSVijendar Mukunda case ACP_CONFIG_18:
3817c0ea26cSVijendar Mukunda case ACP_CONFIG_19:
3827c0ea26cSVijendar Mukunda acp_data->is_pdm_config = true;
3837c0ea26cSVijendar Mukunda acp_data->is_sdw_config = true;
3847c0ea26cSVijendar Mukunda break;
3857c0ea26cSVijendar Mukunda default:
3867c0ea26cSVijendar Mukunda break;
3877c0ea26cSVijendar Mukunda }
3887c0ea26cSVijendar Mukunda }
3897c0ea26cSVijendar Mukunda
acp70_sdw_dma_irq_thread(struct acp63_dev_data * adata)3900b6914a0SVijendar Mukunda static void acp70_sdw_dma_irq_thread(struct acp63_dev_data *adata)
3910b6914a0SVijendar Mukunda {
3920b6914a0SVijendar Mukunda struct sdw_dma_dev_data *sdw_data;
3930b6914a0SVijendar Mukunda u32 stream_id;
3940b6914a0SVijendar Mukunda
3950b6914a0SVijendar Mukunda sdw_data = dev_get_drvdata(&adata->sdw_dma_dev->dev);
3960b6914a0SVijendar Mukunda
3970b6914a0SVijendar Mukunda for (stream_id = 0; stream_id < ACP70_SDW0_DMA_MAX_STREAMS; stream_id++) {
3980b6914a0SVijendar Mukunda if (adata->acp70_sdw0_dma_intr_stat[stream_id]) {
3990b6914a0SVijendar Mukunda if (sdw_data->acp70_sdw0_dma_stream[stream_id])
4000b6914a0SVijendar Mukunda snd_pcm_period_elapsed(sdw_data->acp70_sdw0_dma_stream[stream_id]);
4010b6914a0SVijendar Mukunda adata->acp70_sdw0_dma_intr_stat[stream_id] = 0;
4020b6914a0SVijendar Mukunda }
4030b6914a0SVijendar Mukunda }
4040b6914a0SVijendar Mukunda for (stream_id = 0; stream_id < ACP70_SDW1_DMA_MAX_STREAMS; stream_id++) {
4050b6914a0SVijendar Mukunda if (adata->acp70_sdw1_dma_intr_stat[stream_id]) {
4060b6914a0SVijendar Mukunda if (sdw_data->acp70_sdw1_dma_stream[stream_id])
4070b6914a0SVijendar Mukunda snd_pcm_period_elapsed(sdw_data->acp70_sdw1_dma_stream[stream_id]);
4080b6914a0SVijendar Mukunda adata->acp70_sdw1_dma_intr_stat[stream_id] = 0;
4090b6914a0SVijendar Mukunda }
4100b6914a0SVijendar Mukunda }
4110b6914a0SVijendar Mukunda }
4120b6914a0SVijendar Mukunda
snd_acp70_suspend(struct device * dev)413fde277dbSVijendar Mukunda static int __maybe_unused snd_acp70_suspend(struct device *dev)
414fde277dbSVijendar Mukunda {
415fde277dbSVijendar Mukunda struct acp63_dev_data *adata;
416fde277dbSVijendar Mukunda int ret;
417fde277dbSVijendar Mukunda
418fde277dbSVijendar Mukunda adata = dev_get_drvdata(dev);
419fde277dbSVijendar Mukunda if (adata->is_sdw_dev) {
420*dc6458edSVijendar Mukunda adata->acp_sw_pad_keeper_en = readl(adata->acp63_base + ACP_SW0_PAD_KEEPER_EN);
421*dc6458edSVijendar Mukunda adata->acp_pad_pulldown_ctrl = readl(adata->acp63_base + ACP_PAD_PULLDOWN_CTRL);
422fde277dbSVijendar Mukunda adata->sdw_en_stat = check_acp_sdw_enable_status(adata);
423fde277dbSVijendar Mukunda if (adata->sdw_en_stat) {
424fde277dbSVijendar Mukunda writel(1, adata->acp63_base + ACP_ZSC_DSP_CTRL);
425fde277dbSVijendar Mukunda return 0;
426fde277dbSVijendar Mukunda }
427fde277dbSVijendar Mukunda }
428fde277dbSVijendar Mukunda ret = acp_hw_deinit(adata, dev);
429fde277dbSVijendar Mukunda if (ret)
430fde277dbSVijendar Mukunda dev_err(dev, "ACP de-init failed\n");
431fde277dbSVijendar Mukunda
432fde277dbSVijendar Mukunda return ret;
433fde277dbSVijendar Mukunda }
434fde277dbSVijendar Mukunda
snd_acp70_runtime_resume(struct device * dev)435fde277dbSVijendar Mukunda static int __maybe_unused snd_acp70_runtime_resume(struct device *dev)
436fde277dbSVijendar Mukunda {
437fde277dbSVijendar Mukunda struct acp63_dev_data *adata;
438fde277dbSVijendar Mukunda int ret;
439fde277dbSVijendar Mukunda
440fde277dbSVijendar Mukunda adata = dev_get_drvdata(dev);
441fde277dbSVijendar Mukunda
442fde277dbSVijendar Mukunda if (adata->sdw_en_stat) {
443fde277dbSVijendar Mukunda writel(0, adata->acp63_base + ACP_ZSC_DSP_CTRL);
444fde277dbSVijendar Mukunda writel(1, adata->acp63_base + ACP_PME_EN);
445fde277dbSVijendar Mukunda return 0;
446fde277dbSVijendar Mukunda }
447fde277dbSVijendar Mukunda
448fde277dbSVijendar Mukunda ret = acp_hw_init(adata, dev);
449fde277dbSVijendar Mukunda if (ret) {
450fde277dbSVijendar Mukunda dev_err(dev, "ACP init failed\n");
451fde277dbSVijendar Mukunda return ret;
452fde277dbSVijendar Mukunda }
453fde277dbSVijendar Mukunda return 0;
454fde277dbSVijendar Mukunda }
455fde277dbSVijendar Mukunda
snd_acp70_resume(struct device * dev)456fde277dbSVijendar Mukunda static int __maybe_unused snd_acp70_resume(struct device *dev)
457fde277dbSVijendar Mukunda {
458fde277dbSVijendar Mukunda struct acp63_dev_data *adata;
459*dc6458edSVijendar Mukunda u32 acp_sw_pad_keeper_en;
460fde277dbSVijendar Mukunda int ret;
461fde277dbSVijendar Mukunda
462fde277dbSVijendar Mukunda adata = dev_get_drvdata(dev);
463fde277dbSVijendar Mukunda
464fde277dbSVijendar Mukunda if (adata->sdw_en_stat) {
465fde277dbSVijendar Mukunda writel(0, adata->acp63_base + ACP_ZSC_DSP_CTRL);
466fde277dbSVijendar Mukunda writel(1, adata->acp63_base + ACP_PME_EN);
467fde277dbSVijendar Mukunda return 0;
468fde277dbSVijendar Mukunda }
469fde277dbSVijendar Mukunda
470fde277dbSVijendar Mukunda ret = acp_hw_init(adata, dev);
471fde277dbSVijendar Mukunda if (ret)
472fde277dbSVijendar Mukunda dev_err(dev, "ACP init failed\n");
473fde277dbSVijendar Mukunda
474*dc6458edSVijendar Mukunda acp_sw_pad_keeper_en = readl(adata->acp63_base + ACP_SW0_PAD_KEEPER_EN);
475*dc6458edSVijendar Mukunda dev_dbg(dev, "ACP_SW0_PAD_KEEPER_EN:0x%x\n", acp_sw_pad_keeper_en);
476*dc6458edSVijendar Mukunda if (!acp_sw_pad_keeper_en) {
477*dc6458edSVijendar Mukunda writel(adata->acp_sw_pad_keeper_en, adata->acp63_base + ACP_SW0_PAD_KEEPER_EN);
478*dc6458edSVijendar Mukunda writel(adata->acp_pad_pulldown_ctrl, adata->acp63_base + ACP_PAD_PULLDOWN_CTRL);
479*dc6458edSVijendar Mukunda }
480fde277dbSVijendar Mukunda return ret;
481fde277dbSVijendar Mukunda }
482fde277dbSVijendar Mukunda
acp70_hw_init_ops(struct acp_hw_ops * hw_ops)4837c0ea26cSVijendar Mukunda void acp70_hw_init_ops(struct acp_hw_ops *hw_ops)
4847c0ea26cSVijendar Mukunda {
4857c0ea26cSVijendar Mukunda hw_ops->acp_init = acp70_init;
4867c0ea26cSVijendar Mukunda hw_ops->acp_deinit = acp70_deinit;
4877c0ea26cSVijendar Mukunda hw_ops->acp_get_config = acp70_get_config;
4880b6914a0SVijendar Mukunda hw_ops->acp_sdw_dma_irq_thread = acp70_sdw_dma_irq_thread;
489fde277dbSVijendar Mukunda hw_ops->acp_suspend = snd_acp70_suspend;
490fde277dbSVijendar Mukunda hw_ops->acp_resume = snd_acp70_resume;
491fde277dbSVijendar Mukunda hw_ops->acp_suspend_runtime = snd_acp70_suspend;
492fde277dbSVijendar Mukunda hw_ops->acp_resume_runtime = snd_acp70_runtime_resume;
4937c0ea26cSVijendar Mukunda }
494