1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * AMD ACP PCI driver callback routines for ACP6.3, ACP7.0 & ACP7.1
4 * platforms.
5 *
6 * Copyright 2025 Advanced Micro Devices, Inc.
7 * Authors: Vijendar Mukunda <Vijendar.Mukunda@amd.com>
8 */
9
10 #include <linux/bitops.h>
11 #include <linux/delay.h>
12 #include <linux/export.h>
13 #include <linux/io.h>
14 #include <linux/iopoll.h>
15 #include <linux/pci.h>
16 #include <linux/platform_device.h>
17 #include <linux/pm_runtime.h>
18 #include <sound/pcm_params.h>
19
20 #include "acp63.h"
21
acp63_power_on(void __iomem * acp_base)22 static int acp63_power_on(void __iomem *acp_base)
23 {
24 u32 val;
25
26 val = readl(acp_base + ACP_PGFSM_STATUS);
27
28 if (!val)
29 return val;
30
31 if ((val & ACP63_PGFSM_STATUS_MASK) != ACP63_POWER_ON_IN_PROGRESS)
32 writel(ACP63_PGFSM_CNTL_POWER_ON_MASK, acp_base + ACP_PGFSM_CONTROL);
33
34 return readl_poll_timeout(acp_base + ACP_PGFSM_STATUS, val, !val, DELAY_US, ACP63_TIMEOUT);
35 }
36
acp63_reset(void __iomem * acp_base)37 static int acp63_reset(void __iomem *acp_base)
38 {
39 u32 val;
40 int ret;
41
42 writel(1, acp_base + ACP_SOFT_RESET);
43
44 ret = readl_poll_timeout(acp_base + ACP_SOFT_RESET, val,
45 val & ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK,
46 DELAY_US, ACP63_TIMEOUT);
47 if (ret)
48 return ret;
49
50 writel(0, acp_base + ACP_SOFT_RESET);
51
52 return readl_poll_timeout(acp_base + ACP_SOFT_RESET, val, !val, DELAY_US, ACP63_TIMEOUT);
53 }
54
acp63_enable_interrupts(void __iomem * acp_base)55 static void acp63_enable_interrupts(void __iomem *acp_base)
56 {
57 writel(1, acp_base + ACP_EXTERNAL_INTR_ENB);
58 writel(ACP_ERROR_IRQ, acp_base + ACP_EXTERNAL_INTR_CNTL);
59 }
60
acp63_disable_interrupts(void __iomem * acp_base)61 static void acp63_disable_interrupts(void __iomem *acp_base)
62 {
63 writel(ACP_EXT_INTR_STAT_CLEAR_MASK, acp_base + ACP_EXTERNAL_INTR_STAT);
64 writel(0, acp_base + ACP_EXTERNAL_INTR_CNTL);
65 writel(0, acp_base + ACP_EXTERNAL_INTR_ENB);
66 }
67
acp63_init(void __iomem * acp_base,struct device * dev)68 static int acp63_init(void __iomem *acp_base, struct device *dev)
69 {
70 int ret;
71
72 ret = acp63_power_on(acp_base);
73 if (ret) {
74 dev_err(dev, "ACP power on failed\n");
75 return ret;
76 }
77 writel(0x01, acp_base + ACP_CONTROL);
78 ret = acp63_reset(acp_base);
79 if (ret) {
80 dev_err(dev, "ACP reset failed\n");
81 return ret;
82 }
83 acp63_enable_interrupts(acp_base);
84 writel(0, acp_base + ACP_ZSC_DSP_CTRL);
85 return 0;
86 }
87
acp63_deinit(void __iomem * acp_base,struct device * dev)88 static int acp63_deinit(void __iomem *acp_base, struct device *dev)
89 {
90 int ret;
91
92 acp63_disable_interrupts(acp_base);
93 ret = acp63_reset(acp_base);
94 if (ret) {
95 dev_err(dev, "ACP reset failed\n");
96 return ret;
97 }
98 writel(0, acp_base + ACP_CONTROL);
99 writel(1, acp_base + ACP_ZSC_DSP_CTRL);
100 return 0;
101 }
102
acp63_get_config(struct pci_dev * pci,struct acp63_dev_data * acp_data)103 static void acp63_get_config(struct pci_dev *pci, struct acp63_dev_data *acp_data)
104 {
105 u32 config;
106
107 config = readl(acp_data->acp63_base + ACP_PIN_CONFIG);
108 dev_dbg(&pci->dev, "ACP config value: %d\n", config);
109 switch (config) {
110 case ACP_CONFIG_4:
111 case ACP_CONFIG_5:
112 case ACP_CONFIG_10:
113 case ACP_CONFIG_11:
114 acp_data->is_pdm_config = true;
115 break;
116 case ACP_CONFIG_2:
117 case ACP_CONFIG_3:
118 acp_data->is_sdw_config = true;
119 break;
120 case ACP_CONFIG_6:
121 case ACP_CONFIG_7:
122 case ACP_CONFIG_12:
123 case ACP_CONFIG_8:
124 case ACP_CONFIG_13:
125 case ACP_CONFIG_14:
126 acp_data->is_pdm_config = true;
127 acp_data->is_sdw_config = true;
128 break;
129 default:
130 break;
131 }
132 }
133
check_acp_sdw_enable_status(struct acp63_dev_data * adata)134 static bool check_acp_sdw_enable_status(struct acp63_dev_data *adata)
135 {
136 u32 sdw0_en, sdw1_en;
137
138 sdw0_en = readl(adata->acp63_base + ACP_SW0_EN);
139 sdw1_en = readl(adata->acp63_base + ACP_SW1_EN);
140 return (sdw0_en || sdw1_en);
141 }
142
handle_acp63_sdw_pme_event(struct acp63_dev_data * adata)143 static void handle_acp63_sdw_pme_event(struct acp63_dev_data *adata)
144 {
145 u32 val;
146
147 val = readl(adata->acp63_base + ACP_SW0_WAKE_EN);
148 if (val && adata->sdw->pdev[0])
149 pm_request_resume(&adata->sdw->pdev[0]->dev);
150
151 val = readl(adata->acp63_base + ACP_SW1_WAKE_EN);
152 if (val && adata->sdw->pdev[1])
153 pm_request_resume(&adata->sdw->pdev[1]->dev);
154 }
155
snd_acp63_suspend(struct device * dev)156 static int __maybe_unused snd_acp63_suspend(struct device *dev)
157 {
158 struct acp63_dev_data *adata;
159 int ret;
160
161 adata = dev_get_drvdata(dev);
162 if (adata->is_sdw_dev) {
163 adata->sdw_en_stat = check_acp_sdw_enable_status(adata);
164 if (adata->sdw_en_stat) {
165 writel(1, adata->acp63_base + ACP_ZSC_DSP_CTRL);
166 return 0;
167 }
168 }
169 ret = acp_hw_deinit(adata, dev);
170 if (ret)
171 dev_err(dev, "ACP de-init failed\n");
172
173 return ret;
174 }
175
snd_acp63_runtime_resume(struct device * dev)176 static int __maybe_unused snd_acp63_runtime_resume(struct device *dev)
177 {
178 struct acp63_dev_data *adata;
179 int ret;
180
181 adata = dev_get_drvdata(dev);
182 if (adata->sdw_en_stat) {
183 writel(0, adata->acp63_base + ACP_ZSC_DSP_CTRL);
184 return 0;
185 }
186 ret = acp_hw_init(adata, dev);
187 if (ret) {
188 dev_err(dev, "ACP init failed\n");
189 return ret;
190 }
191
192 if (!adata->sdw_en_stat)
193 handle_acp63_sdw_pme_event(adata);
194 return 0;
195 }
196
snd_acp63_resume(struct device * dev)197 static int __maybe_unused snd_acp63_resume(struct device *dev)
198 {
199 struct acp63_dev_data *adata;
200 int ret;
201
202 adata = dev_get_drvdata(dev);
203 if (adata->sdw_en_stat) {
204 writel(0, adata->acp63_base + ACP_ZSC_DSP_CTRL);
205 return 0;
206 }
207
208 ret = acp_hw_init(adata, dev);
209 if (ret)
210 dev_err(dev, "ACP init failed\n");
211
212 return ret;
213 }
214
acp63_sdw_dma_irq_thread(struct acp63_dev_data * adata)215 static void acp63_sdw_dma_irq_thread(struct acp63_dev_data *adata)
216 {
217 struct sdw_dma_dev_data *sdw_data;
218 u32 stream_id;
219
220 sdw_data = dev_get_drvdata(&adata->sdw_dma_dev->dev);
221
222 for (stream_id = 0; stream_id < ACP63_SDW0_DMA_MAX_STREAMS; stream_id++) {
223 if (adata->acp63_sdw0_dma_intr_stat[stream_id]) {
224 if (sdw_data->acp63_sdw0_dma_stream[stream_id])
225 snd_pcm_period_elapsed(sdw_data->acp63_sdw0_dma_stream[stream_id]);
226 adata->acp63_sdw0_dma_intr_stat[stream_id] = 0;
227 }
228 }
229 for (stream_id = 0; stream_id < ACP63_SDW1_DMA_MAX_STREAMS; stream_id++) {
230 if (adata->acp63_sdw1_dma_intr_stat[stream_id]) {
231 if (sdw_data->acp63_sdw1_dma_stream[stream_id])
232 snd_pcm_period_elapsed(sdw_data->acp63_sdw1_dma_stream[stream_id]);
233 adata->acp63_sdw1_dma_intr_stat[stream_id] = 0;
234 }
235 }
236 }
237
acp63_hw_init_ops(struct acp_hw_ops * hw_ops)238 void acp63_hw_init_ops(struct acp_hw_ops *hw_ops)
239 {
240 hw_ops->acp_init = acp63_init;
241 hw_ops->acp_deinit = acp63_deinit;
242 hw_ops->acp_get_config = acp63_get_config;
243 hw_ops->acp_sdw_dma_irq_thread = acp63_sdw_dma_irq_thread;
244 hw_ops->acp_suspend = snd_acp63_suspend;
245 hw_ops->acp_resume = snd_acp63_resume;
246 hw_ops->acp_suspend_runtime = snd_acp63_suspend;
247 hw_ops->acp_resume_runtime = snd_acp63_runtime_resume;
248 }
249
acp70_power_on(void __iomem * acp_base)250 static int acp70_power_on(void __iomem *acp_base)
251 {
252 u32 val = 0;
253
254 val = readl(acp_base + ACP_PGFSM_STATUS);
255
256 if (!val)
257 return 0;
258 if (val & ACP70_PGFSM_STATUS_MASK)
259 writel(ACP70_PGFSM_CNTL_POWER_ON_MASK, acp_base + ACP_PGFSM_CONTROL);
260
261 return readl_poll_timeout(acp_base + ACP_PGFSM_STATUS, val, !val, DELAY_US, ACP70_TIMEOUT);
262 }
263
acp70_reset(void __iomem * acp_base)264 static int acp70_reset(void __iomem *acp_base)
265 {
266 u32 val;
267 int ret;
268
269 writel(1, acp_base + ACP_SOFT_RESET);
270
271 ret = readl_poll_timeout(acp_base + ACP_SOFT_RESET, val,
272 val & ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK,
273 DELAY_US, ACP70_TIMEOUT);
274 if (ret)
275 return ret;
276
277 writel(0, acp_base + ACP_SOFT_RESET);
278
279 return readl_poll_timeout(acp_base + ACP_SOFT_RESET, val, !val, DELAY_US, ACP70_TIMEOUT);
280 }
281
acp70_enable_sdw_host_wake_interrupts(void __iomem * acp_base)282 static void acp70_enable_sdw_host_wake_interrupts(void __iomem *acp_base)
283 {
284 u32 ext_intr_cntl1;
285
286 ext_intr_cntl1 = readl(acp_base + ACP_EXTERNAL_INTR_CNTL1);
287 ext_intr_cntl1 |= ACP70_SDW_HOST_WAKE_MASK;
288 writel(ext_intr_cntl1, acp_base + ACP_EXTERNAL_INTR_CNTL1);
289 }
290
acp70_enable_interrupts(void __iomem * acp_base)291 static void acp70_enable_interrupts(void __iomem *acp_base)
292 {
293 u32 sdw0_wake_en, sdw1_wake_en;
294
295 writel(1, acp_base + ACP_EXTERNAL_INTR_ENB);
296 writel(ACP_ERROR_IRQ, acp_base + ACP_EXTERNAL_INTR_CNTL);
297 sdw0_wake_en = readl(acp_base + ACP_SW0_WAKE_EN);
298 sdw1_wake_en = readl(acp_base + ACP_SW1_WAKE_EN);
299 if (sdw0_wake_en || sdw1_wake_en)
300 acp70_enable_sdw_host_wake_interrupts(acp_base);
301 }
302
acp70_disable_interrupts(void __iomem * acp_base)303 static void acp70_disable_interrupts(void __iomem *acp_base)
304 {
305 writel(ACP_EXT_INTR_STAT_CLEAR_MASK, acp_base + ACP_EXTERNAL_INTR_STAT);
306 writel(0, acp_base + ACP_EXTERNAL_INTR_CNTL);
307 writel(0, acp_base + ACP_EXTERNAL_INTR_ENB);
308 }
309
acp70_init(void __iomem * acp_base,struct device * dev)310 static int acp70_init(void __iomem *acp_base, struct device *dev)
311 {
312 int ret;
313
314 ret = acp70_power_on(acp_base);
315 if (ret) {
316 dev_err(dev, "ACP power on failed\n");
317 return ret;
318 }
319 writel(0x01, acp_base + ACP_CONTROL);
320 ret = acp70_reset(acp_base);
321 if (ret) {
322 dev_err(dev, "ACP reset failed\n");
323 return ret;
324 }
325 writel(0, acp_base + ACP_ZSC_DSP_CTRL);
326 acp70_enable_interrupts(acp_base);
327 writel(0x1, acp_base + ACP_PME_EN);
328 return 0;
329 }
330
acp70_deinit(void __iomem * acp_base,struct device * dev)331 static int acp70_deinit(void __iomem *acp_base, struct device *dev)
332 {
333 int ret;
334
335 acp70_disable_interrupts(acp_base);
336 ret = acp70_reset(acp_base);
337 if (ret) {
338 dev_err(dev, "ACP reset failed\n");
339 return ret;
340 }
341 writel(0x01, acp_base + ACP_ZSC_DSP_CTRL);
342 return 0;
343 }
344
acp70_get_config(struct pci_dev * pci,struct acp63_dev_data * acp_data)345 static void acp70_get_config(struct pci_dev *pci, struct acp63_dev_data *acp_data)
346 {
347 u32 config;
348
349 config = readl(acp_data->acp63_base + ACP_PIN_CONFIG);
350 dev_dbg(&pci->dev, "ACP config value: %d\n", config);
351 switch (config) {
352 case ACP_CONFIG_4:
353 case ACP_CONFIG_5:
354 case ACP_CONFIG_10:
355 case ACP_CONFIG_11:
356 case ACP_CONFIG_20:
357 acp_data->is_pdm_config = true;
358 break;
359 case ACP_CONFIG_2:
360 case ACP_CONFIG_3:
361 case ACP_CONFIG_16:
362 acp_data->is_sdw_config = true;
363 break;
364 case ACP_CONFIG_6:
365 case ACP_CONFIG_7:
366 case ACP_CONFIG_12:
367 case ACP_CONFIG_8:
368 case ACP_CONFIG_13:
369 case ACP_CONFIG_14:
370 case ACP_CONFIG_17:
371 case ACP_CONFIG_18:
372 case ACP_CONFIG_19:
373 acp_data->is_pdm_config = true;
374 acp_data->is_sdw_config = true;
375 break;
376 default:
377 break;
378 }
379 }
380
acp70_sdw_dma_irq_thread(struct acp63_dev_data * adata)381 static void acp70_sdw_dma_irq_thread(struct acp63_dev_data *adata)
382 {
383 struct sdw_dma_dev_data *sdw_data;
384 u32 stream_id;
385
386 sdw_data = dev_get_drvdata(&adata->sdw_dma_dev->dev);
387
388 for (stream_id = 0; stream_id < ACP70_SDW0_DMA_MAX_STREAMS; stream_id++) {
389 if (adata->acp70_sdw0_dma_intr_stat[stream_id]) {
390 if (sdw_data->acp70_sdw0_dma_stream[stream_id])
391 snd_pcm_period_elapsed(sdw_data->acp70_sdw0_dma_stream[stream_id]);
392 adata->acp70_sdw0_dma_intr_stat[stream_id] = 0;
393 }
394 }
395 for (stream_id = 0; stream_id < ACP70_SDW1_DMA_MAX_STREAMS; stream_id++) {
396 if (adata->acp70_sdw1_dma_intr_stat[stream_id]) {
397 if (sdw_data->acp70_sdw1_dma_stream[stream_id])
398 snd_pcm_period_elapsed(sdw_data->acp70_sdw1_dma_stream[stream_id]);
399 adata->acp70_sdw1_dma_intr_stat[stream_id] = 0;
400 }
401 }
402 }
403
snd_acp70_suspend(struct device * dev)404 static int __maybe_unused snd_acp70_suspend(struct device *dev)
405 {
406 struct acp63_dev_data *adata;
407 int ret;
408
409 adata = dev_get_drvdata(dev);
410 if (adata->is_sdw_dev) {
411 adata->sdw_en_stat = check_acp_sdw_enable_status(adata);
412 if (adata->sdw_en_stat) {
413 writel(1, adata->acp63_base + ACP_ZSC_DSP_CTRL);
414 return 0;
415 }
416 }
417 ret = acp_hw_deinit(adata, dev);
418 if (ret)
419 dev_err(dev, "ACP de-init failed\n");
420
421 return ret;
422 }
423
snd_acp70_runtime_resume(struct device * dev)424 static int __maybe_unused snd_acp70_runtime_resume(struct device *dev)
425 {
426 struct acp63_dev_data *adata;
427 int ret;
428
429 adata = dev_get_drvdata(dev);
430
431 if (adata->sdw_en_stat) {
432 writel(0, adata->acp63_base + ACP_ZSC_DSP_CTRL);
433 writel(1, adata->acp63_base + ACP_PME_EN);
434 return 0;
435 }
436
437 ret = acp_hw_init(adata, dev);
438 if (ret) {
439 dev_err(dev, "ACP init failed\n");
440 return ret;
441 }
442 return 0;
443 }
444
snd_acp70_resume(struct device * dev)445 static int __maybe_unused snd_acp70_resume(struct device *dev)
446 {
447 struct acp63_dev_data *adata;
448 int ret;
449
450 adata = dev_get_drvdata(dev);
451
452 if (adata->sdw_en_stat) {
453 writel(0, adata->acp63_base + ACP_ZSC_DSP_CTRL);
454 writel(1, adata->acp63_base + ACP_PME_EN);
455 return 0;
456 }
457
458 ret = acp_hw_init(adata, dev);
459 if (ret)
460 dev_err(dev, "ACP init failed\n");
461
462 return ret;
463 }
464
acp70_hw_init_ops(struct acp_hw_ops * hw_ops)465 void acp70_hw_init_ops(struct acp_hw_ops *hw_ops)
466 {
467 hw_ops->acp_init = acp70_init;
468 hw_ops->acp_deinit = acp70_deinit;
469 hw_ops->acp_get_config = acp70_get_config;
470 hw_ops->acp_sdw_dma_irq_thread = acp70_sdw_dma_irq_thread;
471 hw_ops->acp_suspend = snd_acp70_suspend;
472 hw_ops->acp_resume = snd_acp70_resume;
473 hw_ops->acp_suspend_runtime = snd_acp70_suspend;
474 hw_ops->acp_resume_runtime = snd_acp70_runtime_resume;
475 }
476