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->acp_sw_pad_keeper_en = readl(adata->acp63_base + ACP_SW0_PAD_KEEPER_EN);
164 adata->acp_pad_pulldown_ctrl = readl(adata->acp63_base + ACP_PAD_PULLDOWN_CTRL);
165 adata->sdw_en_stat = check_acp_sdw_enable_status(adata);
166 if (adata->sdw_en_stat) {
167 writel(1, adata->acp63_base + ACP_ZSC_DSP_CTRL);
168 return 0;
169 }
170 }
171 ret = acp_hw_deinit(adata, dev);
172 if (ret)
173 dev_err(dev, "ACP de-init failed\n");
174
175 return ret;
176 }
177
snd_acp63_runtime_resume(struct device * dev)178 static int __maybe_unused snd_acp63_runtime_resume(struct device *dev)
179 {
180 struct acp63_dev_data *adata;
181 int ret;
182
183 adata = dev_get_drvdata(dev);
184 if (adata->sdw_en_stat) {
185 writel(0, adata->acp63_base + ACP_ZSC_DSP_CTRL);
186 return 0;
187 }
188 ret = acp_hw_init(adata, dev);
189 if (ret) {
190 dev_err(dev, "ACP init failed\n");
191 return ret;
192 }
193
194 if (!adata->sdw_en_stat)
195 handle_acp63_sdw_pme_event(adata);
196 return 0;
197 }
198
snd_acp63_resume(struct device * dev)199 static int __maybe_unused snd_acp63_resume(struct device *dev)
200 {
201 struct acp63_dev_data *adata;
202 u32 acp_sw_pad_keeper_en;
203 int ret;
204
205 adata = dev_get_drvdata(dev);
206 if (adata->sdw_en_stat) {
207 writel(0, adata->acp63_base + ACP_ZSC_DSP_CTRL);
208 return 0;
209 }
210
211 ret = acp_hw_init(adata, dev);
212 if (ret)
213 dev_err(dev, "ACP init failed\n");
214
215 acp_sw_pad_keeper_en = readl(adata->acp63_base + ACP_SW0_PAD_KEEPER_EN);
216 dev_dbg(dev, "ACP_SW0_PAD_KEEPER_EN:0x%x\n", acp_sw_pad_keeper_en);
217 if (!acp_sw_pad_keeper_en) {
218 writel(adata->acp_sw_pad_keeper_en, adata->acp63_base + ACP_SW0_PAD_KEEPER_EN);
219 writel(adata->acp_pad_pulldown_ctrl, adata->acp63_base + ACP_PAD_PULLDOWN_CTRL);
220 }
221 return ret;
222 }
223
acp63_sdw_dma_irq_thread(struct acp63_dev_data * adata)224 static void acp63_sdw_dma_irq_thread(struct acp63_dev_data *adata)
225 {
226 struct sdw_dma_dev_data *sdw_data;
227 u32 stream_id;
228
229 sdw_data = dev_get_drvdata(&adata->sdw_dma_dev->dev);
230
231 for (stream_id = 0; stream_id < ACP63_SDW0_DMA_MAX_STREAMS; stream_id++) {
232 if (adata->acp63_sdw0_dma_intr_stat[stream_id]) {
233 if (sdw_data->acp63_sdw0_dma_stream[stream_id])
234 snd_pcm_period_elapsed(sdw_data->acp63_sdw0_dma_stream[stream_id]);
235 adata->acp63_sdw0_dma_intr_stat[stream_id] = 0;
236 }
237 }
238 for (stream_id = 0; stream_id < ACP63_SDW1_DMA_MAX_STREAMS; stream_id++) {
239 if (adata->acp63_sdw1_dma_intr_stat[stream_id]) {
240 if (sdw_data->acp63_sdw1_dma_stream[stream_id])
241 snd_pcm_period_elapsed(sdw_data->acp63_sdw1_dma_stream[stream_id]);
242 adata->acp63_sdw1_dma_intr_stat[stream_id] = 0;
243 }
244 }
245 }
246
acp63_hw_init_ops(struct acp_hw_ops * hw_ops)247 void acp63_hw_init_ops(struct acp_hw_ops *hw_ops)
248 {
249 hw_ops->acp_init = acp63_init;
250 hw_ops->acp_deinit = acp63_deinit;
251 hw_ops->acp_get_config = acp63_get_config;
252 hw_ops->acp_sdw_dma_irq_thread = acp63_sdw_dma_irq_thread;
253 hw_ops->acp_suspend = snd_acp63_suspend;
254 hw_ops->acp_resume = snd_acp63_resume;
255 hw_ops->acp_suspend_runtime = snd_acp63_suspend;
256 hw_ops->acp_resume_runtime = snd_acp63_runtime_resume;
257 }
258
acp70_power_on(void __iomem * acp_base)259 static int acp70_power_on(void __iomem *acp_base)
260 {
261 u32 val = 0;
262
263 val = readl(acp_base + ACP_PGFSM_STATUS);
264
265 if (!val)
266 return 0;
267 if (val & ACP70_PGFSM_STATUS_MASK)
268 writel(ACP70_PGFSM_CNTL_POWER_ON_MASK, acp_base + ACP_PGFSM_CONTROL);
269
270 return readl_poll_timeout(acp_base + ACP_PGFSM_STATUS, val, !val, DELAY_US, ACP70_TIMEOUT);
271 }
272
acp70_reset(void __iomem * acp_base)273 static int acp70_reset(void __iomem *acp_base)
274 {
275 u32 val;
276 int ret;
277
278 writel(1, acp_base + ACP_SOFT_RESET);
279
280 ret = readl_poll_timeout(acp_base + ACP_SOFT_RESET, val,
281 val & ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK,
282 DELAY_US, ACP70_TIMEOUT);
283 if (ret)
284 return ret;
285
286 writel(0, acp_base + ACP_SOFT_RESET);
287
288 return readl_poll_timeout(acp_base + ACP_SOFT_RESET, val, !val, DELAY_US, ACP70_TIMEOUT);
289 }
290
acp70_enable_sdw_host_wake_interrupts(void __iomem * acp_base)291 static void acp70_enable_sdw_host_wake_interrupts(void __iomem *acp_base)
292 {
293 u32 ext_intr_cntl1;
294
295 ext_intr_cntl1 = readl(acp_base + ACP_EXTERNAL_INTR_CNTL1);
296 ext_intr_cntl1 |= ACP70_SDW_HOST_WAKE_MASK;
297 writel(ext_intr_cntl1, acp_base + ACP_EXTERNAL_INTR_CNTL1);
298 }
299
acp70_enable_interrupts(void __iomem * acp_base)300 static void acp70_enable_interrupts(void __iomem *acp_base)
301 {
302 u32 sdw0_wake_en, sdw1_wake_en;
303
304 writel(1, acp_base + ACP_EXTERNAL_INTR_ENB);
305 writel(ACP_ERROR_IRQ, acp_base + ACP_EXTERNAL_INTR_CNTL);
306 sdw0_wake_en = readl(acp_base + ACP_SW0_WAKE_EN);
307 sdw1_wake_en = readl(acp_base + ACP_SW1_WAKE_EN);
308 if (sdw0_wake_en || sdw1_wake_en)
309 acp70_enable_sdw_host_wake_interrupts(acp_base);
310 }
311
acp70_disable_interrupts(void __iomem * acp_base)312 static void acp70_disable_interrupts(void __iomem *acp_base)
313 {
314 writel(ACP_EXT_INTR_STAT_CLEAR_MASK, acp_base + ACP_EXTERNAL_INTR_STAT);
315 writel(0, acp_base + ACP_EXTERNAL_INTR_CNTL);
316 writel(0, acp_base + ACP_EXTERNAL_INTR_ENB);
317 }
318
acp70_init(void __iomem * acp_base,struct device * dev)319 static int acp70_init(void __iomem *acp_base, struct device *dev)
320 {
321 int ret;
322
323 ret = acp70_power_on(acp_base);
324 if (ret) {
325 dev_err(dev, "ACP power on failed\n");
326 return ret;
327 }
328 writel(0x01, acp_base + ACP_CONTROL);
329 ret = acp70_reset(acp_base);
330 if (ret) {
331 dev_err(dev, "ACP reset failed\n");
332 return ret;
333 }
334 writel(0, acp_base + ACP_ZSC_DSP_CTRL);
335 acp70_enable_interrupts(acp_base);
336 writel(0x1, acp_base + ACP_PME_EN);
337 return 0;
338 }
339
acp70_deinit(void __iomem * acp_base,struct device * dev)340 static int acp70_deinit(void __iomem *acp_base, struct device *dev)
341 {
342 int ret;
343
344 acp70_disable_interrupts(acp_base);
345 ret = acp70_reset(acp_base);
346 if (ret) {
347 dev_err(dev, "ACP reset failed\n");
348 return ret;
349 }
350 writel(0x01, acp_base + ACP_ZSC_DSP_CTRL);
351 return 0;
352 }
353
acp70_get_config(struct pci_dev * pci,struct acp63_dev_data * acp_data)354 static void acp70_get_config(struct pci_dev *pci, struct acp63_dev_data *acp_data)
355 {
356 u32 config;
357
358 config = readl(acp_data->acp63_base + ACP_PIN_CONFIG);
359 dev_dbg(&pci->dev, "ACP config value: %d\n", config);
360 switch (config) {
361 case ACP_CONFIG_4:
362 case ACP_CONFIG_5:
363 case ACP_CONFIG_10:
364 case ACP_CONFIG_11:
365 case ACP_CONFIG_20:
366 acp_data->is_pdm_config = true;
367 break;
368 case ACP_CONFIG_2:
369 case ACP_CONFIG_3:
370 case ACP_CONFIG_16:
371 acp_data->is_sdw_config = true;
372 break;
373 case ACP_CONFIG_6:
374 case ACP_CONFIG_7:
375 case ACP_CONFIG_12:
376 case ACP_CONFIG_8:
377 case ACP_CONFIG_13:
378 case ACP_CONFIG_14:
379 case ACP_CONFIG_17:
380 case ACP_CONFIG_18:
381 case ACP_CONFIG_19:
382 acp_data->is_pdm_config = true;
383 acp_data->is_sdw_config = true;
384 break;
385 default:
386 break;
387 }
388 }
389
acp70_sdw_dma_irq_thread(struct acp63_dev_data * adata)390 static void acp70_sdw_dma_irq_thread(struct acp63_dev_data *adata)
391 {
392 struct sdw_dma_dev_data *sdw_data;
393 u32 stream_id;
394
395 sdw_data = dev_get_drvdata(&adata->sdw_dma_dev->dev);
396
397 for (stream_id = 0; stream_id < ACP70_SDW0_DMA_MAX_STREAMS; stream_id++) {
398 if (adata->acp70_sdw0_dma_intr_stat[stream_id]) {
399 if (sdw_data->acp70_sdw0_dma_stream[stream_id])
400 snd_pcm_period_elapsed(sdw_data->acp70_sdw0_dma_stream[stream_id]);
401 adata->acp70_sdw0_dma_intr_stat[stream_id] = 0;
402 }
403 }
404 for (stream_id = 0; stream_id < ACP70_SDW1_DMA_MAX_STREAMS; stream_id++) {
405 if (adata->acp70_sdw1_dma_intr_stat[stream_id]) {
406 if (sdw_data->acp70_sdw1_dma_stream[stream_id])
407 snd_pcm_period_elapsed(sdw_data->acp70_sdw1_dma_stream[stream_id]);
408 adata->acp70_sdw1_dma_intr_stat[stream_id] = 0;
409 }
410 }
411 }
412
snd_acp70_suspend(struct device * dev)413 static int __maybe_unused snd_acp70_suspend(struct device *dev)
414 {
415 struct acp63_dev_data *adata;
416 int ret;
417
418 adata = dev_get_drvdata(dev);
419 if (adata->is_sdw_dev) {
420 adata->acp_sw_pad_keeper_en = readl(adata->acp63_base + ACP_SW0_PAD_KEEPER_EN);
421 adata->acp_pad_pulldown_ctrl = readl(adata->acp63_base + ACP_PAD_PULLDOWN_CTRL);
422 adata->sdw_en_stat = check_acp_sdw_enable_status(adata);
423 if (adata->sdw_en_stat) {
424 writel(1, adata->acp63_base + ACP_ZSC_DSP_CTRL);
425 return 0;
426 }
427 }
428 ret = acp_hw_deinit(adata, dev);
429 if (ret)
430 dev_err(dev, "ACP de-init failed\n");
431
432 return ret;
433 }
434
snd_acp70_runtime_resume(struct device * dev)435 static int __maybe_unused snd_acp70_runtime_resume(struct device *dev)
436 {
437 struct acp63_dev_data *adata;
438 int ret;
439
440 adata = dev_get_drvdata(dev);
441
442 if (adata->sdw_en_stat) {
443 writel(0, adata->acp63_base + ACP_ZSC_DSP_CTRL);
444 writel(1, adata->acp63_base + ACP_PME_EN);
445 return 0;
446 }
447
448 ret = acp_hw_init(adata, dev);
449 if (ret) {
450 dev_err(dev, "ACP init failed\n");
451 return ret;
452 }
453 return 0;
454 }
455
snd_acp70_resume(struct device * dev)456 static int __maybe_unused snd_acp70_resume(struct device *dev)
457 {
458 struct acp63_dev_data *adata;
459 u32 acp_sw_pad_keeper_en;
460 int ret;
461
462 adata = dev_get_drvdata(dev);
463
464 if (adata->sdw_en_stat) {
465 writel(0, adata->acp63_base + ACP_ZSC_DSP_CTRL);
466 writel(1, adata->acp63_base + ACP_PME_EN);
467 return 0;
468 }
469
470 ret = acp_hw_init(adata, dev);
471 if (ret)
472 dev_err(dev, "ACP init failed\n");
473
474 acp_sw_pad_keeper_en = readl(adata->acp63_base + ACP_SW0_PAD_KEEPER_EN);
475 dev_dbg(dev, "ACP_SW0_PAD_KEEPER_EN:0x%x\n", acp_sw_pad_keeper_en);
476 if (!acp_sw_pad_keeper_en) {
477 writel(adata->acp_sw_pad_keeper_en, adata->acp63_base + ACP_SW0_PAD_KEEPER_EN);
478 writel(adata->acp_pad_pulldown_ctrl, adata->acp63_base + ACP_PAD_PULLDOWN_CTRL);
479 }
480 return ret;
481 }
482
acp70_hw_init_ops(struct acp_hw_ops * hw_ops)483 void acp70_hw_init_ops(struct acp_hw_ops *hw_ops)
484 {
485 hw_ops->acp_init = acp70_init;
486 hw_ops->acp_deinit = acp70_deinit;
487 hw_ops->acp_get_config = acp70_get_config;
488 hw_ops->acp_sdw_dma_irq_thread = acp70_sdw_dma_irq_thread;
489 hw_ops->acp_suspend = snd_acp70_suspend;
490 hw_ops->acp_resume = snd_acp70_resume;
491 hw_ops->acp_suspend_runtime = snd_acp70_suspend;
492 hw_ops->acp_resume_runtime = snd_acp70_runtime_resume;
493 }
494