blob: ecbc9c79bcad35cc3637cbd6b0f536c02a24384f [file] [log] [blame]
Liam Girdwood9e42c5c2019-04-12 11:08:44 -05001// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
2//
3// This file is provided under a dual BSD/GPLv2 license. When using or
4// redistributing this file, you may do so under either license.
5//
6// Copyright(c) 2018 Intel Corporation. All rights reserved.
7//
8// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
9//
10
11/*
12 * Hardware interface for audio DSP on Baytrail, Braswell and Cherrytrail.
13 */
14
15#include <linux/module.h>
16#include <sound/sof.h>
17#include <sound/sof/xtensa.h>
18#include "../ops.h"
19#include "shim.h"
20
21/* DSP memories */
22#define IRAM_OFFSET 0x0C0000
23#define IRAM_SIZE (80 * 1024)
24#define DRAM_OFFSET 0x100000
25#define DRAM_SIZE (160 * 1024)
26#define SHIM_OFFSET 0x140000
27#define SHIM_SIZE 0x100
28#define MBOX_OFFSET 0x144000
29#define MBOX_SIZE 0x1000
30#define EXCEPT_OFFSET 0x800
31
32/* DSP peripherals */
33#define DMAC0_OFFSET 0x098000
34#define DMAC1_OFFSET 0x09c000
35#define DMAC2_OFFSET 0x094000
36#define DMAC_SIZE 0x420
37#define SSP0_OFFSET 0x0a0000
38#define SSP1_OFFSET 0x0a1000
39#define SSP2_OFFSET 0x0a2000
40#define SSP3_OFFSET 0x0a4000
41#define SSP4_OFFSET 0x0a5000
42#define SSP5_OFFSET 0x0a6000
43#define SSP_SIZE 0x100
44
45#define BYT_STACK_DUMP_SIZE 32
46
47#define BYT_PCI_BAR_SIZE 0x200000
48
49#define BYT_PANIC_OFFSET(x) (((x) & GENMASK_ULL(47, 32)) >> 32)
50
51/*
52 * Debug
53 */
54
55#define MBOX_DUMP_SIZE 0x30
56
57/* BARs */
58#define BYT_DSP_BAR 0
59#define BYT_PCI_BAR 1
60#define BYT_IMR_BAR 2
61
62static const struct snd_sof_debugfs_map byt_debugfs[] = {
63 {"dmac0", BYT_DSP_BAR, DMAC0_OFFSET, DMAC_SIZE,
64 SOF_DEBUGFS_ACCESS_ALWAYS},
65 {"dmac1", BYT_DSP_BAR, DMAC1_OFFSET, DMAC_SIZE,
66 SOF_DEBUGFS_ACCESS_ALWAYS},
67 {"ssp0", BYT_DSP_BAR, SSP0_OFFSET, SSP_SIZE,
68 SOF_DEBUGFS_ACCESS_ALWAYS},
69 {"ssp1", BYT_DSP_BAR, SSP1_OFFSET, SSP_SIZE,
70 SOF_DEBUGFS_ACCESS_ALWAYS},
71 {"ssp2", BYT_DSP_BAR, SSP2_OFFSET, SSP_SIZE,
72 SOF_DEBUGFS_ACCESS_ALWAYS},
73 {"iram", BYT_DSP_BAR, IRAM_OFFSET, IRAM_SIZE,
74 SOF_DEBUGFS_ACCESS_D0_ONLY},
75 {"dram", BYT_DSP_BAR, DRAM_OFFSET, DRAM_SIZE,
76 SOF_DEBUGFS_ACCESS_D0_ONLY},
77 {"shim", BYT_DSP_BAR, SHIM_OFFSET, SHIM_SIZE,
78 SOF_DEBUGFS_ACCESS_ALWAYS},
79};
80
81static const struct snd_sof_debugfs_map cht_debugfs[] = {
82 {"dmac0", BYT_DSP_BAR, DMAC0_OFFSET, DMAC_SIZE,
83 SOF_DEBUGFS_ACCESS_ALWAYS},
84 {"dmac1", BYT_DSP_BAR, DMAC1_OFFSET, DMAC_SIZE,
85 SOF_DEBUGFS_ACCESS_ALWAYS},
86 {"dmac2", BYT_DSP_BAR, DMAC2_OFFSET, DMAC_SIZE,
87 SOF_DEBUGFS_ACCESS_ALWAYS},
88 {"ssp0", BYT_DSP_BAR, SSP0_OFFSET, SSP_SIZE,
89 SOF_DEBUGFS_ACCESS_ALWAYS},
90 {"ssp1", BYT_DSP_BAR, SSP1_OFFSET, SSP_SIZE,
91 SOF_DEBUGFS_ACCESS_ALWAYS},
92 {"ssp2", BYT_DSP_BAR, SSP2_OFFSET, SSP_SIZE,
93 SOF_DEBUGFS_ACCESS_ALWAYS},
94 {"ssp3", BYT_DSP_BAR, SSP3_OFFSET, SSP_SIZE,
95 SOF_DEBUGFS_ACCESS_ALWAYS},
96 {"ssp4", BYT_DSP_BAR, SSP4_OFFSET, SSP_SIZE,
97 SOF_DEBUGFS_ACCESS_ALWAYS},
98 {"ssp5", BYT_DSP_BAR, SSP5_OFFSET, SSP_SIZE,
99 SOF_DEBUGFS_ACCESS_ALWAYS},
100 {"iram", BYT_DSP_BAR, IRAM_OFFSET, IRAM_SIZE,
101 SOF_DEBUGFS_ACCESS_D0_ONLY},
102 {"dram", BYT_DSP_BAR, DRAM_OFFSET, DRAM_SIZE,
103 SOF_DEBUGFS_ACCESS_D0_ONLY},
104 {"shim", BYT_DSP_BAR, SHIM_OFFSET, SHIM_SIZE,
105 SOF_DEBUGFS_ACCESS_ALWAYS},
106};
107
108static void byt_host_done(struct snd_sof_dev *sdev);
109static void byt_dsp_done(struct snd_sof_dev *sdev);
110static void byt_get_reply(struct snd_sof_dev *sdev);
111
112/*
Liam Girdwood9e42c5c2019-04-12 11:08:44 -0500113 * Debug
114 */
115
116static void byt_get_registers(struct snd_sof_dev *sdev,
117 struct sof_ipc_dsp_oops_xtensa *xoops,
118 struct sof_ipc_panic_info *panic_info,
119 u32 *stack, size_t stack_words)
120{
Kai Vehmanen14104eb2019-06-03 11:18:15 -0500121 u32 offset = sdev->dsp_oops_offset;
122
Liam Girdwood9e42c5c2019-04-12 11:08:44 -0500123 /* first read regsisters */
Kai Vehmanen14104eb2019-06-03 11:18:15 -0500124 sof_mailbox_read(sdev, offset, xoops, sizeof(*xoops));
125
126 /* note: variable AR register array is not read */
Liam Girdwood9e42c5c2019-04-12 11:08:44 -0500127
128 /* then get panic info */
Kai Vehmanen14104eb2019-06-03 11:18:15 -0500129 offset += xoops->arch_hdr.totalsize;
130 sof_mailbox_read(sdev, offset, panic_info, sizeof(*panic_info));
Liam Girdwood9e42c5c2019-04-12 11:08:44 -0500131
132 /* then get the stack */
Kai Vehmanen14104eb2019-06-03 11:18:15 -0500133 offset += sizeof(*panic_info);
134 sof_mailbox_read(sdev, offset, stack, stack_words * sizeof(u32));
Liam Girdwood9e42c5c2019-04-12 11:08:44 -0500135}
136
137static void byt_dump(struct snd_sof_dev *sdev, u32 flags)
138{
139 struct sof_ipc_dsp_oops_xtensa xoops;
140 struct sof_ipc_panic_info panic_info;
141 u32 stack[BYT_STACK_DUMP_SIZE];
Liam Girdwood3a9e2042019-09-27 15:05:37 -0500142 u32 status, panic, imrd, imrx;
Liam Girdwood9e42c5c2019-04-12 11:08:44 -0500143
144 /* now try generic SOF status messages */
145 status = snd_sof_dsp_read(sdev, BYT_DSP_BAR, SHIM_IPCD);
146 panic = snd_sof_dsp_read(sdev, BYT_DSP_BAR, SHIM_IPCX);
147 byt_get_registers(sdev, &xoops, &panic_info, stack,
148 BYT_STACK_DUMP_SIZE);
149 snd_sof_get_status(sdev, status, panic, &xoops, &panic_info, stack,
150 BYT_STACK_DUMP_SIZE);
Liam Girdwood3a9e2042019-09-27 15:05:37 -0500151
152 /* provide some context for firmware debug */
153 imrx = snd_sof_dsp_read(sdev, BYT_DSP_BAR, SHIM_IMRX);
154 imrd = snd_sof_dsp_read(sdev, BYT_DSP_BAR, SHIM_IMRD);
155 dev_err(sdev->dev,
156 "error: ipc host -> DSP: pending %s complete %s raw 0x%8.8x\n",
157 panic & SHIM_IPCX_BUSY ? "yes" : "no",
158 panic & SHIM_IPCX_DONE ? "yes" : "no", panic);
159 dev_err(sdev->dev,
160 "error: mask host: pending %s complete %s raw 0x%8.8x\n",
161 imrx & SHIM_IMRX_BUSY ? "yes" : "no",
162 imrx & SHIM_IMRX_DONE ? "yes" : "no", imrx);
163 dev_err(sdev->dev,
164 "error: ipc DSP -> host: pending %s complete %s raw 0x%8.8x\n",
165 status & SHIM_IPCD_BUSY ? "yes" : "no",
166 status & SHIM_IPCD_DONE ? "yes" : "no", status);
167 dev_err(sdev->dev,
168 "error: mask DSP: pending %s complete %s raw 0x%8.8x\n",
169 imrd & SHIM_IMRD_BUSY ? "yes" : "no",
170 imrd & SHIM_IMRD_DONE ? "yes" : "no", imrd);
171
Liam Girdwood9e42c5c2019-04-12 11:08:44 -0500172}
173
174/*
175 * IPC Doorbell IRQ handler and thread.
176 */
177
178static irqreturn_t byt_irq_handler(int irq, void *context)
179{
180 struct snd_sof_dev *sdev = context;
181 u64 isr;
182 int ret = IRQ_NONE;
183
184 /* Interrupt arrived, check src */
185 isr = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_ISRX);
186 if (isr & (SHIM_ISRX_DONE | SHIM_ISRX_BUSY))
187 ret = IRQ_WAKE_THREAD;
188
189 return ret;
190}
191
192static irqreturn_t byt_irq_thread(int irq, void *context)
193{
194 struct snd_sof_dev *sdev = context;
195 u64 ipcx, ipcd;
196 u64 imrx;
197
198 imrx = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_IMRX);
199 ipcx = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_IPCX);
200
201 /* reply message from DSP */
202 if (ipcx & SHIM_BYT_IPCX_DONE &&
203 !(imrx & SHIM_IMRX_DONE)) {
204 /* Mask Done interrupt before first */
205 snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR,
206 SHIM_IMRX,
207 SHIM_IMRX_DONE,
208 SHIM_IMRX_DONE);
Guennadi Liakhovetski1183e9a2019-05-24 14:09:23 -0500209
210 spin_lock_irq(&sdev->ipc_lock);
211
Liam Girdwood9e42c5c2019-04-12 11:08:44 -0500212 /*
213 * handle immediate reply from DSP core. If the msg is
214 * found, set done bit in cmd_done which is called at the
215 * end of message processing function, else set it here
216 * because the done bit can't be set in cmd_done function
217 * which is triggered by msg
218 */
219 byt_get_reply(sdev);
220 snd_sof_ipc_reply(sdev, ipcx);
221
222 byt_dsp_done(sdev);
Guennadi Liakhovetski1183e9a2019-05-24 14:09:23 -0500223
224 spin_unlock_irq(&sdev->ipc_lock);
Liam Girdwood9e42c5c2019-04-12 11:08:44 -0500225 }
226
227 /* new message from DSP */
228 ipcd = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_IPCD);
229 if (ipcd & SHIM_BYT_IPCD_BUSY &&
230 !(imrx & SHIM_IMRX_BUSY)) {
231 /* Mask Busy interrupt before return */
232 snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR,
233 SHIM_IMRX,
234 SHIM_IMRX_BUSY,
235 SHIM_IMRX_BUSY);
236
237 /* Handle messages from DSP Core */
238 if ((ipcd & SOF_IPC_PANIC_MAGIC_MASK) == SOF_IPC_PANIC_MAGIC) {
239 snd_sof_dsp_panic(sdev, BYT_PANIC_OFFSET(ipcd) +
240 MBOX_OFFSET);
241 } else {
242 snd_sof_ipc_msgs_rx(sdev);
243 }
244
245 byt_host_done(sdev);
246 }
247
248 return IRQ_HANDLED;
249}
250
251static int byt_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg)
252{
Liam Girdwood9e42c5c2019-04-12 11:08:44 -0500253 /* send the message */
254 sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data,
255 msg->msg_size);
Daniel Baluta6fbbc182019-06-03 11:20:25 -0500256 snd_sof_dsp_write64(sdev, BYT_DSP_BAR, SHIM_IPCX, SHIM_BYT_IPCX_BUSY);
Liam Girdwood9e42c5c2019-04-12 11:08:44 -0500257
258 return 0;
259}
260
261static void byt_get_reply(struct snd_sof_dev *sdev)
262{
263 struct snd_sof_ipc_msg *msg = sdev->msg;
264 struct sof_ipc_reply reply;
Liam Girdwood9e42c5c2019-04-12 11:08:44 -0500265 int ret = 0;
266
267 /*
268 * Sometimes, there is unexpected reply ipc arriving. The reply
269 * ipc belongs to none of the ipcs sent from driver.
270 * In this case, the driver must ignore the ipc.
271 */
272 if (!msg) {
273 dev_warn(sdev->dev, "unexpected ipc interrupt raised!\n");
274 return;
275 }
276
277 /* get reply */
278 sof_mailbox_read(sdev, sdev->host_box.offset, &reply, sizeof(reply));
279
Liam Girdwood9e42c5c2019-04-12 11:08:44 -0500280 if (reply.error < 0) {
281 memcpy(msg->reply_data, &reply, sizeof(reply));
282 ret = reply.error;
283 } else {
284 /* reply correct size ? */
285 if (reply.hdr.size != msg->reply_size) {
286 dev_err(sdev->dev, "error: reply expected %zu got %u bytes\n",
287 msg->reply_size, reply.hdr.size);
288 ret = -EINVAL;
289 }
290
291 /* read the message */
292 if (msg->reply_size > 0)
293 sof_mailbox_read(sdev, sdev->host_box.offset,
294 msg->reply_data, msg->reply_size);
295 }
296
297 msg->reply_error = ret;
Liam Girdwood9e42c5c2019-04-12 11:08:44 -0500298}
299
Daniel Baluta83ee7ab2019-08-07 10:02:01 -0500300static int byt_get_mailbox_offset(struct snd_sof_dev *sdev)
301{
302 return MBOX_OFFSET;
303}
304
305static int byt_get_window_offset(struct snd_sof_dev *sdev, u32 id)
306{
307 return MBOX_OFFSET;
308}
309
Liam Girdwood9e42c5c2019-04-12 11:08:44 -0500310static void byt_host_done(struct snd_sof_dev *sdev)
311{
312 /* clear BUSY bit and set DONE bit - accept new messages */
313 snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, SHIM_IPCD,
314 SHIM_BYT_IPCD_BUSY |
315 SHIM_BYT_IPCD_DONE,
316 SHIM_BYT_IPCD_DONE);
317
318 /* unmask busy interrupt */
319 snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, SHIM_IMRX,
320 SHIM_IMRX_BUSY, 0);
321}
322
323static void byt_dsp_done(struct snd_sof_dev *sdev)
324{
325 /* clear DONE bit - tell DSP we have completed */
326 snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, SHIM_IPCX,
327 SHIM_BYT_IPCX_DONE, 0);
328
329 /* unmask Done interrupt */
330 snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, SHIM_IMRX,
331 SHIM_IMRX_DONE, 0);
332}
333
334/*
335 * DSP control.
336 */
337
338static int byt_run(struct snd_sof_dev *sdev)
339{
340 int tries = 10;
341
342 /* release stall and wait to unstall */
343 snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_CSR,
344 SHIM_BYT_CSR_STALL, 0x0);
345 while (tries--) {
346 if (!(snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_CSR) &
347 SHIM_BYT_CSR_PWAITMODE))
348 break;
349 msleep(100);
350 }
351 if (tries < 0) {
352 dev_err(sdev->dev, "error: unable to run DSP firmware\n");
353 byt_dump(sdev, SOF_DBG_REGS | SOF_DBG_MBOX);
354 return -ENODEV;
355 }
356
357 /* return init core mask */
358 return 1;
359}
360
361static int byt_reset(struct snd_sof_dev *sdev)
362{
363 /* put DSP into reset, set reset vector and stall */
364 snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_CSR,
365 SHIM_BYT_CSR_RST | SHIM_BYT_CSR_VECTOR_SEL |
366 SHIM_BYT_CSR_STALL,
367 SHIM_BYT_CSR_RST | SHIM_BYT_CSR_VECTOR_SEL |
368 SHIM_BYT_CSR_STALL);
369
370 usleep_range(10, 15);
371
372 /* take DSP out of reset and keep stalled for FW loading */
373 snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_CSR,
374 SHIM_BYT_CSR_RST, 0);
375
376 return 0;
377}
378
379/* Baytrail DAIs */
380static struct snd_soc_dai_driver byt_dai[] = {
381{
382 .name = "ssp0-port",
383},
384{
385 .name = "ssp1-port",
386},
387{
388 .name = "ssp2-port",
389},
390{
391 .name = "ssp3-port",
392},
393{
394 .name = "ssp4-port",
395},
396{
397 .name = "ssp5-port",
398},
399};
400
401/*
402 * Probe and remove.
403 */
404
405#if IS_ENABLED(CONFIG_SND_SOC_SOF_MERRIFIELD)
406
407static int tangier_pci_probe(struct snd_sof_dev *sdev)
408{
409 struct snd_sof_pdata *pdata = sdev->pdata;
410 const struct sof_dev_desc *desc = pdata->desc;
411 struct pci_dev *pci = to_pci_dev(sdev->dev);
412 u32 base, size;
413 int ret;
414
415 /* DSP DMA can only access low 31 bits of host memory */
416 ret = dma_coerce_mask_and_coherent(&pci->dev, DMA_BIT_MASK(31));
417 if (ret < 0) {
418 dev_err(sdev->dev, "error: failed to set DMA mask %d\n", ret);
419 return ret;
420 }
421
422 /* LPE base */
423 base = pci_resource_start(pci, desc->resindex_lpe_base) - IRAM_OFFSET;
424 size = BYT_PCI_BAR_SIZE;
425
426 dev_dbg(sdev->dev, "LPE PHY base at 0x%x size 0x%x", base, size);
427 sdev->bar[BYT_DSP_BAR] = devm_ioremap(sdev->dev, base, size);
428 if (!sdev->bar[BYT_DSP_BAR]) {
429 dev_err(sdev->dev, "error: failed to ioremap LPE base 0x%x size 0x%x\n",
430 base, size);
431 return -ENODEV;
432 }
433 dev_dbg(sdev->dev, "LPE VADDR %p\n", sdev->bar[BYT_DSP_BAR]);
434
435 /* IMR base - optional */
436 if (desc->resindex_imr_base == -1)
437 goto irq;
438
439 base = pci_resource_start(pci, desc->resindex_imr_base);
440 size = pci_resource_len(pci, desc->resindex_imr_base);
441
442 /* some BIOSes don't map IMR */
443 if (base == 0x55aa55aa || base == 0x0) {
444 dev_info(sdev->dev, "IMR not set by BIOS. Ignoring\n");
445 goto irq;
446 }
447
448 dev_dbg(sdev->dev, "IMR base at 0x%x size 0x%x", base, size);
449 sdev->bar[BYT_IMR_BAR] = devm_ioremap(sdev->dev, base, size);
450 if (!sdev->bar[BYT_IMR_BAR]) {
451 dev_err(sdev->dev, "error: failed to ioremap IMR base 0x%x size 0x%x\n",
452 base, size);
453 return -ENODEV;
454 }
455 dev_dbg(sdev->dev, "IMR VADDR %p\n", sdev->bar[BYT_IMR_BAR]);
456
457irq:
458 /* register our IRQ */
459 sdev->ipc_irq = pci->irq;
460 dev_dbg(sdev->dev, "using IRQ %d\n", sdev->ipc_irq);
461 ret = devm_request_threaded_irq(sdev->dev, sdev->ipc_irq,
462 byt_irq_handler, byt_irq_thread,
463 0, "AudioDSP", sdev);
464 if (ret < 0) {
465 dev_err(sdev->dev, "error: failed to register IRQ %d\n",
466 sdev->ipc_irq);
467 return ret;
468 }
469
470 /* enable Interrupt from both sides */
471 snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRX, 0x3, 0x0);
472 snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRD, 0x3, 0x0);
473
474 /* set default mailbox offset for FW ready message */
475 sdev->dsp_box.offset = MBOX_OFFSET;
476
477 return ret;
478}
479
480const struct snd_sof_dsp_ops sof_tng_ops = {
481 /* device init */
482 .probe = tangier_pci_probe,
483
484 /* DSP core boot / reset */
485 .run = byt_run,
486 .reset = byt_reset,
487
488 /* Register IO */
489 .write = sof_io_write,
490 .read = sof_io_read,
491 .write64 = sof_io_write64,
492 .read64 = sof_io_read64,
493
494 /* Block IO */
495 .block_read = sof_block_read,
496 .block_write = sof_block_write,
497
498 /* doorbell */
499 .irq_handler = byt_irq_handler,
500 .irq_thread = byt_irq_thread,
501
502 /* ipc */
503 .send_msg = byt_send_msg,
Daniel Baluta83ee7ab2019-08-07 10:02:01 -0500504 .fw_ready = sof_fw_ready,
505 .get_mailbox_offset = byt_get_mailbox_offset,
506 .get_window_offset = byt_get_window_offset,
Liam Girdwood9e42c5c2019-04-12 11:08:44 -0500507
508 .ipc_msg_data = intel_ipc_msg_data,
509 .ipc_pcm_params = intel_ipc_pcm_params,
510
511 /* debug */
512 .debug_map = byt_debugfs,
513 .debug_map_count = ARRAY_SIZE(byt_debugfs),
514 .dbg_dump = byt_dump,
515
516 /* stream callbacks */
517 .pcm_open = intel_pcm_open,
518 .pcm_close = intel_pcm_close,
519
520 /* module loading */
521 .load_module = snd_sof_parse_module_memcpy,
522
523 /*Firmware loading */
524 .load_firmware = snd_sof_load_firmware_memcpy,
525
526 /* DAI drivers */
527 .drv = byt_dai,
528 .num_drv = 3, /* we have only 3 SSPs on byt*/
529};
530EXPORT_SYMBOL(sof_tng_ops);
531
532const struct sof_intel_dsp_desc tng_chip_info = {
533 .cores_num = 1,
534 .cores_mask = 1,
535};
536EXPORT_SYMBOL(tng_chip_info);
537
538#endif /* CONFIG_SND_SOC_SOF_MERRIFIELD */
539
540#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL)
541
542static int byt_acpi_probe(struct snd_sof_dev *sdev)
543{
544 struct snd_sof_pdata *pdata = sdev->pdata;
545 const struct sof_dev_desc *desc = pdata->desc;
546 struct platform_device *pdev =
547 container_of(sdev->dev, struct platform_device, dev);
548 struct resource *mmio;
549 u32 base, size;
550 int ret;
551
552 /* DSP DMA can only access low 31 bits of host memory */
553 ret = dma_coerce_mask_and_coherent(sdev->dev, DMA_BIT_MASK(31));
554 if (ret < 0) {
555 dev_err(sdev->dev, "error: failed to set DMA mask %d\n", ret);
556 return ret;
557 }
558
559 /* LPE base */
560 mmio = platform_get_resource(pdev, IORESOURCE_MEM,
561 desc->resindex_lpe_base);
562 if (mmio) {
563 base = mmio->start;
564 size = resource_size(mmio);
565 } else {
566 dev_err(sdev->dev, "error: failed to get LPE base at idx %d\n",
567 desc->resindex_lpe_base);
568 return -EINVAL;
569 }
570
571 dev_dbg(sdev->dev, "LPE PHY base at 0x%x size 0x%x", base, size);
572 sdev->bar[BYT_DSP_BAR] = devm_ioremap(sdev->dev, base, size);
573 if (!sdev->bar[BYT_DSP_BAR]) {
574 dev_err(sdev->dev, "error: failed to ioremap LPE base 0x%x size 0x%x\n",
575 base, size);
576 return -ENODEV;
577 }
578 dev_dbg(sdev->dev, "LPE VADDR %p\n", sdev->bar[BYT_DSP_BAR]);
579
580 /* TODO: add offsets */
581 sdev->mmio_bar = BYT_DSP_BAR;
582 sdev->mailbox_bar = BYT_DSP_BAR;
583
584 /* IMR base - optional */
585 if (desc->resindex_imr_base == -1)
586 goto irq;
587
588 mmio = platform_get_resource(pdev, IORESOURCE_MEM,
589 desc->resindex_imr_base);
590 if (mmio) {
591 base = mmio->start;
592 size = resource_size(mmio);
593 } else {
594 dev_err(sdev->dev, "error: failed to get IMR base at idx %d\n",
595 desc->resindex_imr_base);
596 return -ENODEV;
597 }
598
599 /* some BIOSes don't map IMR */
600 if (base == 0x55aa55aa || base == 0x0) {
601 dev_info(sdev->dev, "IMR not set by BIOS. Ignoring\n");
602 goto irq;
603 }
604
605 dev_dbg(sdev->dev, "IMR base at 0x%x size 0x%x", base, size);
606 sdev->bar[BYT_IMR_BAR] = devm_ioremap(sdev->dev, base, size);
607 if (!sdev->bar[BYT_IMR_BAR]) {
608 dev_err(sdev->dev, "error: failed to ioremap IMR base 0x%x size 0x%x\n",
609 base, size);
610 return -ENODEV;
611 }
612 dev_dbg(sdev->dev, "IMR VADDR %p\n", sdev->bar[BYT_IMR_BAR]);
613
614irq:
615 /* register our IRQ */
616 sdev->ipc_irq = platform_get_irq(pdev, desc->irqindex_host_ipc);
Stephen Boydcf9441a2019-07-30 11:15:49 -0700617 if (sdev->ipc_irq < 0)
Liam Girdwood9e42c5c2019-04-12 11:08:44 -0500618 return sdev->ipc_irq;
Liam Girdwood9e42c5c2019-04-12 11:08:44 -0500619
620 dev_dbg(sdev->dev, "using IRQ %d\n", sdev->ipc_irq);
621 ret = devm_request_threaded_irq(sdev->dev, sdev->ipc_irq,
622 byt_irq_handler, byt_irq_thread,
623 IRQF_SHARED, "AudioDSP", sdev);
624 if (ret < 0) {
625 dev_err(sdev->dev, "error: failed to register IRQ %d\n",
626 sdev->ipc_irq);
627 return ret;
628 }
629
630 /* enable Interrupt from both sides */
631 snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRX, 0x3, 0x0);
632 snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRD, 0x3, 0x0);
633
634 /* set default mailbox offset for FW ready message */
635 sdev->dsp_box.offset = MBOX_OFFSET;
636
637 return ret;
638}
639
640/* baytrail ops */
641const struct snd_sof_dsp_ops sof_byt_ops = {
642 /* device init */
643 .probe = byt_acpi_probe,
644
645 /* DSP core boot / reset */
646 .run = byt_run,
647 .reset = byt_reset,
648
649 /* Register IO */
650 .write = sof_io_write,
651 .read = sof_io_read,
652 .write64 = sof_io_write64,
653 .read64 = sof_io_read64,
654
655 /* Block IO */
656 .block_read = sof_block_read,
657 .block_write = sof_block_write,
658
659 /* doorbell */
660 .irq_handler = byt_irq_handler,
661 .irq_thread = byt_irq_thread,
662
663 /* ipc */
664 .send_msg = byt_send_msg,
Daniel Baluta83ee7ab2019-08-07 10:02:01 -0500665 .fw_ready = sof_fw_ready,
666 .get_mailbox_offset = byt_get_mailbox_offset,
667 .get_window_offset = byt_get_window_offset,
Liam Girdwood9e42c5c2019-04-12 11:08:44 -0500668
669 .ipc_msg_data = intel_ipc_msg_data,
670 .ipc_pcm_params = intel_ipc_pcm_params,
671
672 /* debug */
673 .debug_map = byt_debugfs,
674 .debug_map_count = ARRAY_SIZE(byt_debugfs),
675 .dbg_dump = byt_dump,
676
677 /* stream callbacks */
678 .pcm_open = intel_pcm_open,
679 .pcm_close = intel_pcm_close,
680
681 /* module loading */
682 .load_module = snd_sof_parse_module_memcpy,
683
684 /*Firmware loading */
685 .load_firmware = snd_sof_load_firmware_memcpy,
686
687 /* DAI drivers */
688 .drv = byt_dai,
689 .num_drv = 3, /* we have only 3 SSPs on byt*/
690};
691EXPORT_SYMBOL(sof_byt_ops);
692
693const struct sof_intel_dsp_desc byt_chip_info = {
694 .cores_num = 1,
695 .cores_mask = 1,
696};
697EXPORT_SYMBOL(byt_chip_info);
698
699/* cherrytrail and braswell ops */
700const struct snd_sof_dsp_ops sof_cht_ops = {
701 /* device init */
702 .probe = byt_acpi_probe,
703
704 /* DSP core boot / reset */
705 .run = byt_run,
706 .reset = byt_reset,
707
708 /* Register IO */
709 .write = sof_io_write,
710 .read = sof_io_read,
711 .write64 = sof_io_write64,
712 .read64 = sof_io_read64,
713
714 /* Block IO */
715 .block_read = sof_block_read,
716 .block_write = sof_block_write,
717
718 /* doorbell */
719 .irq_handler = byt_irq_handler,
720 .irq_thread = byt_irq_thread,
721
722 /* ipc */
723 .send_msg = byt_send_msg,
Daniel Baluta83ee7ab2019-08-07 10:02:01 -0500724 .fw_ready = sof_fw_ready,
725 .get_mailbox_offset = byt_get_mailbox_offset,
726 .get_window_offset = byt_get_window_offset,
Liam Girdwood9e42c5c2019-04-12 11:08:44 -0500727
728 .ipc_msg_data = intel_ipc_msg_data,
729 .ipc_pcm_params = intel_ipc_pcm_params,
730
731 /* debug */
732 .debug_map = cht_debugfs,
733 .debug_map_count = ARRAY_SIZE(cht_debugfs),
734 .dbg_dump = byt_dump,
735
736 /* stream callbacks */
737 .pcm_open = intel_pcm_open,
738 .pcm_close = intel_pcm_close,
739
740 /* module loading */
741 .load_module = snd_sof_parse_module_memcpy,
742
743 /*Firmware loading */
744 .load_firmware = snd_sof_load_firmware_memcpy,
745
746 /* DAI drivers */
747 .drv = byt_dai,
748 /* all 6 SSPs may be available for cherrytrail */
749 .num_drv = ARRAY_SIZE(byt_dai),
750};
751EXPORT_SYMBOL(sof_cht_ops);
752
753const struct sof_intel_dsp_desc cht_chip_info = {
754 .cores_num = 1,
755 .cores_mask = 1,
756};
757EXPORT_SYMBOL(cht_chip_info);
758
759#endif /* CONFIG_SND_SOC_SOF_BAYTRAIL */
760
761MODULE_LICENSE("Dual BSD/GPL");