xref: /linux/sound/soc/amd/acp7x/acp7x-common.c (revision 0eaed89c18aeedf0898baf2dbf5ff027c6795152)
1b5a2fdc5SVijendar Mukunda // SPDX-License-Identifier: GPL-2.0-only
2b5a2fdc5SVijendar Mukunda /*
3b5a2fdc5SVijendar Mukunda  * AMD ACP PCI driver callback routines for ACP7.x
4b5a2fdc5SVijendar Mukunda  * platforms.
5b5a2fdc5SVijendar Mukunda  *
6b5a2fdc5SVijendar Mukunda  * Copyright 2026 Advanced Micro Devices, Inc.
7b5a2fdc5SVijendar Mukunda  */
8b5a2fdc5SVijendar Mukunda 
9b5a2fdc5SVijendar Mukunda #include <linux/device.h>
10b5a2fdc5SVijendar Mukunda #include <linux/io.h>
11b5a2fdc5SVijendar Mukunda #include <linux/iopoll.h>
12b5a2fdc5SVijendar Mukunda #include <linux/types.h>
13b5a2fdc5SVijendar Mukunda 
14b5a2fdc5SVijendar Mukunda #include "acp7x.h"
15b5a2fdc5SVijendar Mukunda 
16b5a2fdc5SVijendar Mukunda static int acp7x_power_on(void __iomem *acp_base)
17b5a2fdc5SVijendar Mukunda {
18b5a2fdc5SVijendar Mukunda 	u32 val = 0;
19b5a2fdc5SVijendar Mukunda 
20b5a2fdc5SVijendar Mukunda 	val = readl(acp_base + ACP_PGFSM_STATUS);
21b5a2fdc5SVijendar Mukunda 	if (!(val & ACP7X_PGFSM_STATUS_MASK))
22b5a2fdc5SVijendar Mukunda 		return 0;
23b5a2fdc5SVijendar Mukunda 
24b5a2fdc5SVijendar Mukunda 	writel(ACP7X_PGFSM_CNTL_POWER_ON_MASK, acp_base + ACP_PGFSM_CONTROL);
25b5a2fdc5SVijendar Mukunda 	val = readl(acp_base + ACP_PGFSM_CONTROL);
26b5a2fdc5SVijendar Mukunda 	return readl_poll_timeout(acp_base + ACP_PGFSM_STATUS, val,
27b5a2fdc5SVijendar Mukunda 				  ((val & ACP7X_PGFSM_STATUS_MASK) == 0), DELAY_US, ACP7X_TIMEOUT);
28b5a2fdc5SVijendar Mukunda }
29b5a2fdc5SVijendar Mukunda 
30b5a2fdc5SVijendar Mukunda static int acp7x_reset(void __iomem *acp_base)
31b5a2fdc5SVijendar Mukunda {
32b5a2fdc5SVijendar Mukunda 	u32 val;
33b5a2fdc5SVijendar Mukunda 	int ret;
34b5a2fdc5SVijendar Mukunda 
35b5a2fdc5SVijendar Mukunda 	writel(1, acp_base + ACP_SOFT_RESET);
36b5a2fdc5SVijendar Mukunda 	ret = readl_poll_timeout(acp_base + ACP_SOFT_RESET, val,
37b5a2fdc5SVijendar Mukunda 				 val & ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK,
38b5a2fdc5SVijendar Mukunda 				 DELAY_US, ACP7X_TIMEOUT);
39b5a2fdc5SVijendar Mukunda 	if (ret)
40b5a2fdc5SVijendar Mukunda 		return ret;
41b5a2fdc5SVijendar Mukunda 
42b5a2fdc5SVijendar Mukunda 	writel(0, acp_base + ACP_SOFT_RESET);
43b5a2fdc5SVijendar Mukunda 	return readl_poll_timeout(acp_base + ACP_SOFT_RESET, val, !val, DELAY_US, ACP7X_TIMEOUT);
44b5a2fdc5SVijendar Mukunda }
45b5a2fdc5SVijendar Mukunda 
46b5a2fdc5SVijendar Mukunda static int acp7x_init(void __iomem *acp_base, struct device *dev)
47b5a2fdc5SVijendar Mukunda {
48b5a2fdc5SVijendar Mukunda 	int ret;
49b5a2fdc5SVijendar Mukunda 
50b5a2fdc5SVijendar Mukunda 	ret = acp7x_power_on(acp_base);
51b5a2fdc5SVijendar Mukunda 	if (ret) {
52b5a2fdc5SVijendar Mukunda 		dev_err(dev, "ACP power on failed\n");
53b5a2fdc5SVijendar Mukunda 		return ret;
54b5a2fdc5SVijendar Mukunda 	}
55b5a2fdc5SVijendar Mukunda 	writel(0x01, acp_base + ACP_CONTROL);
56b5a2fdc5SVijendar Mukunda 	ret = acp7x_reset(acp_base);
57b5a2fdc5SVijendar Mukunda 	if (ret) {
58b5a2fdc5SVijendar Mukunda 		dev_err(dev, "ACP reset failed\n");
59b5a2fdc5SVijendar Mukunda 		return ret;
60b5a2fdc5SVijendar Mukunda 	}
61b5a2fdc5SVijendar Mukunda 	writel(0, acp_base + ACP_ZSC_DSP_CTRL);
62b5a2fdc5SVijendar Mukunda 	return 0;
63b5a2fdc5SVijendar Mukunda }
64b5a2fdc5SVijendar Mukunda 
65b5a2fdc5SVijendar Mukunda static int acp7x_deinit(void __iomem *acp_base, struct device *dev)
66b5a2fdc5SVijendar Mukunda {
67b5a2fdc5SVijendar Mukunda 	int ret;
68b5a2fdc5SVijendar Mukunda 
69b5a2fdc5SVijendar Mukunda 	ret = acp7x_reset(acp_base);
70b5a2fdc5SVijendar Mukunda 	if (ret) {
71b5a2fdc5SVijendar Mukunda 		dev_err(dev, "ACP reset failed\n");
72b5a2fdc5SVijendar Mukunda 		return ret;
73b5a2fdc5SVijendar Mukunda 	}
74b5a2fdc5SVijendar Mukunda 	writel(0x01, acp_base + ACP_ZSC_DSP_CTRL);
75b5a2fdc5SVijendar Mukunda 	return 0;
76b5a2fdc5SVijendar Mukunda }
77b5a2fdc5SVijendar Mukunda 
78*07d56a83SVijendar Mukunda static int __maybe_unused snd_acp7x_suspend(struct device *dev)
79*07d56a83SVijendar Mukunda {
80*07d56a83SVijendar Mukunda 	struct acp7x_dev_data *adata;
81*07d56a83SVijendar Mukunda 	int ret;
82*07d56a83SVijendar Mukunda 
83*07d56a83SVijendar Mukunda 	adata = dev_get_drvdata(dev);
84*07d56a83SVijendar Mukunda 	ret = acp_hw_deinit(adata, dev);
85*07d56a83SVijendar Mukunda 	if (ret)
86*07d56a83SVijendar Mukunda 		dev_err(dev, "ACP de-init failed\n");
87*07d56a83SVijendar Mukunda 	return ret;
88*07d56a83SVijendar Mukunda }
89*07d56a83SVijendar Mukunda 
90*07d56a83SVijendar Mukunda static int __maybe_unused snd_acp7x_runtime_resume(struct device *dev)
91*07d56a83SVijendar Mukunda {
92*07d56a83SVijendar Mukunda 	struct acp7x_dev_data *adata;
93*07d56a83SVijendar Mukunda 	int ret;
94*07d56a83SVijendar Mukunda 
95*07d56a83SVijendar Mukunda 	adata = dev_get_drvdata(dev);
96*07d56a83SVijendar Mukunda 	ret = acp_hw_init(adata, dev);
97*07d56a83SVijendar Mukunda 	if (ret) {
98*07d56a83SVijendar Mukunda 		dev_err(dev, "ACP init failed\n");
99*07d56a83SVijendar Mukunda 		return ret;
100*07d56a83SVijendar Mukunda 	}
101*07d56a83SVijendar Mukunda 	return 0;
102*07d56a83SVijendar Mukunda }
103*07d56a83SVijendar Mukunda 
104*07d56a83SVijendar Mukunda static int __maybe_unused snd_acp7x_resume(struct device *dev)
105*07d56a83SVijendar Mukunda {
106*07d56a83SVijendar Mukunda 	struct acp7x_dev_data *adata;
107*07d56a83SVijendar Mukunda 	int ret;
108*07d56a83SVijendar Mukunda 
109*07d56a83SVijendar Mukunda 	adata = dev_get_drvdata(dev);
110*07d56a83SVijendar Mukunda 	ret = acp_hw_init(adata, dev);
111*07d56a83SVijendar Mukunda 	if (ret)
112*07d56a83SVijendar Mukunda 		dev_err(dev, "ACP init failed\n");
113*07d56a83SVijendar Mukunda 
114*07d56a83SVijendar Mukunda 	return ret;
115*07d56a83SVijendar Mukunda }
116*07d56a83SVijendar Mukunda 
117b5a2fdc5SVijendar Mukunda void acp7x_hw_init_ops(struct acp_hw_ops *hw_ops)
118b5a2fdc5SVijendar Mukunda {
119b5a2fdc5SVijendar Mukunda 	hw_ops->acp_init = acp7x_init;
120b5a2fdc5SVijendar Mukunda 	hw_ops->acp_deinit = acp7x_deinit;
121*07d56a83SVijendar Mukunda 	hw_ops->acp_suspend = snd_acp7x_suspend;
122*07d56a83SVijendar Mukunda 	hw_ops->acp_resume = snd_acp7x_resume;
123*07d56a83SVijendar Mukunda 	hw_ops->acp_suspend_runtime = snd_acp7x_suspend;
124*07d56a83SVijendar Mukunda 	hw_ops->acp_resume_runtime = snd_acp7x_runtime_resume;
125b5a2fdc5SVijendar Mukunda }
126