xref: /linux/sound/soc/sof/intel/byt.c (revision 17cfcb68af3bc7d5e8ae08779b1853310a2949f3)
1 // 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 
62 static 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 
81 static 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 
108 static void byt_host_done(struct snd_sof_dev *sdev);
109 static void byt_dsp_done(struct snd_sof_dev *sdev);
110 static void byt_get_reply(struct snd_sof_dev *sdev);
111 
112 /*
113  * Debug
114  */
115 
116 static 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 {
121 	u32 offset = sdev->dsp_oops_offset;
122 
123 	/* first read regsisters */
124 	sof_mailbox_read(sdev, offset, xoops, sizeof(*xoops));
125 
126 	/* note: variable AR register array is not read */
127 
128 	/* then get panic info */
129 	offset += xoops->arch_hdr.totalsize;
130 	sof_mailbox_read(sdev, offset, panic_info, sizeof(*panic_info));
131 
132 	/* then get the stack */
133 	offset += sizeof(*panic_info);
134 	sof_mailbox_read(sdev, offset, stack, stack_words * sizeof(u32));
135 }
136 
137 static 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];
142 	u32 status, panic;
143 
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);
151 }
152 
153 /*
154  * IPC Doorbell IRQ handler and thread.
155  */
156 
157 static irqreturn_t byt_irq_handler(int irq, void *context)
158 {
159 	struct snd_sof_dev *sdev = context;
160 	u64 isr;
161 	int ret = IRQ_NONE;
162 
163 	/* Interrupt arrived, check src */
164 	isr = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_ISRX);
165 	if (isr & (SHIM_ISRX_DONE | SHIM_ISRX_BUSY))
166 		ret = IRQ_WAKE_THREAD;
167 
168 	return ret;
169 }
170 
171 static irqreturn_t byt_irq_thread(int irq, void *context)
172 {
173 	struct snd_sof_dev *sdev = context;
174 	u64 ipcx, ipcd;
175 	u64 imrx;
176 
177 	imrx = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_IMRX);
178 	ipcx = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_IPCX);
179 
180 	/* reply message from DSP */
181 	if (ipcx & SHIM_BYT_IPCX_DONE &&
182 	    !(imrx & SHIM_IMRX_DONE)) {
183 		/* Mask Done interrupt before first */
184 		snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR,
185 						   SHIM_IMRX,
186 						   SHIM_IMRX_DONE,
187 						   SHIM_IMRX_DONE);
188 
189 		spin_lock_irq(&sdev->ipc_lock);
190 
191 		/*
192 		 * handle immediate reply from DSP core. If the msg is
193 		 * found, set done bit in cmd_done which is called at the
194 		 * end of message processing function, else set it here
195 		 * because the done bit can't be set in cmd_done function
196 		 * which is triggered by msg
197 		 */
198 		byt_get_reply(sdev);
199 		snd_sof_ipc_reply(sdev, ipcx);
200 
201 		byt_dsp_done(sdev);
202 
203 		spin_unlock_irq(&sdev->ipc_lock);
204 	}
205 
206 	/* new message from DSP */
207 	ipcd = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_IPCD);
208 	if (ipcd & SHIM_BYT_IPCD_BUSY &&
209 	    !(imrx & SHIM_IMRX_BUSY)) {
210 		/* Mask Busy interrupt before return */
211 		snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR,
212 						   SHIM_IMRX,
213 						   SHIM_IMRX_BUSY,
214 						   SHIM_IMRX_BUSY);
215 
216 		/* Handle messages from DSP Core */
217 		if ((ipcd & SOF_IPC_PANIC_MAGIC_MASK) == SOF_IPC_PANIC_MAGIC) {
218 			snd_sof_dsp_panic(sdev, BYT_PANIC_OFFSET(ipcd) +
219 					  MBOX_OFFSET);
220 		} else {
221 			snd_sof_ipc_msgs_rx(sdev);
222 		}
223 
224 		byt_host_done(sdev);
225 	}
226 
227 	return IRQ_HANDLED;
228 }
229 
230 static int byt_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg)
231 {
232 	/* send the message */
233 	sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data,
234 			  msg->msg_size);
235 	snd_sof_dsp_write64(sdev, BYT_DSP_BAR, SHIM_IPCX, SHIM_BYT_IPCX_BUSY);
236 
237 	return 0;
238 }
239 
240 static void byt_get_reply(struct snd_sof_dev *sdev)
241 {
242 	struct snd_sof_ipc_msg *msg = sdev->msg;
243 	struct sof_ipc_reply reply;
244 	int ret = 0;
245 
246 	/*
247 	 * Sometimes, there is unexpected reply ipc arriving. The reply
248 	 * ipc belongs to none of the ipcs sent from driver.
249 	 * In this case, the driver must ignore the ipc.
250 	 */
251 	if (!msg) {
252 		dev_warn(sdev->dev, "unexpected ipc interrupt raised!\n");
253 		return;
254 	}
255 
256 	/* get reply */
257 	sof_mailbox_read(sdev, sdev->host_box.offset, &reply, sizeof(reply));
258 
259 	if (reply.error < 0) {
260 		memcpy(msg->reply_data, &reply, sizeof(reply));
261 		ret = reply.error;
262 	} else {
263 		/* reply correct size ? */
264 		if (reply.hdr.size != msg->reply_size) {
265 			dev_err(sdev->dev, "error: reply expected %zu got %u bytes\n",
266 				msg->reply_size, reply.hdr.size);
267 			ret = -EINVAL;
268 		}
269 
270 		/* read the message */
271 		if (msg->reply_size > 0)
272 			sof_mailbox_read(sdev, sdev->host_box.offset,
273 					 msg->reply_data, msg->reply_size);
274 	}
275 
276 	msg->reply_error = ret;
277 }
278 
279 static int byt_get_mailbox_offset(struct snd_sof_dev *sdev)
280 {
281 	return MBOX_OFFSET;
282 }
283 
284 static int byt_get_window_offset(struct snd_sof_dev *sdev, u32 id)
285 {
286 	return MBOX_OFFSET;
287 }
288 
289 static void byt_host_done(struct snd_sof_dev *sdev)
290 {
291 	/* clear BUSY bit and set DONE bit - accept new messages */
292 	snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, SHIM_IPCD,
293 					   SHIM_BYT_IPCD_BUSY |
294 					   SHIM_BYT_IPCD_DONE,
295 					   SHIM_BYT_IPCD_DONE);
296 
297 	/* unmask busy interrupt */
298 	snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, SHIM_IMRX,
299 					   SHIM_IMRX_BUSY, 0);
300 }
301 
302 static void byt_dsp_done(struct snd_sof_dev *sdev)
303 {
304 	/* clear DONE bit - tell DSP we have completed */
305 	snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, SHIM_IPCX,
306 					   SHIM_BYT_IPCX_DONE, 0);
307 
308 	/* unmask Done interrupt */
309 	snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, SHIM_IMRX,
310 					   SHIM_IMRX_DONE, 0);
311 }
312 
313 /*
314  * DSP control.
315  */
316 
317 static int byt_run(struct snd_sof_dev *sdev)
318 {
319 	int tries = 10;
320 
321 	/* release stall and wait to unstall */
322 	snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_CSR,
323 				  SHIM_BYT_CSR_STALL, 0x0);
324 	while (tries--) {
325 		if (!(snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_CSR) &
326 		      SHIM_BYT_CSR_PWAITMODE))
327 			break;
328 		msleep(100);
329 	}
330 	if (tries < 0) {
331 		dev_err(sdev->dev, "error:  unable to run DSP firmware\n");
332 		byt_dump(sdev, SOF_DBG_REGS | SOF_DBG_MBOX);
333 		return -ENODEV;
334 	}
335 
336 	/* return init core mask */
337 	return 1;
338 }
339 
340 static int byt_reset(struct snd_sof_dev *sdev)
341 {
342 	/* put DSP into reset, set reset vector and stall */
343 	snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_CSR,
344 				  SHIM_BYT_CSR_RST | SHIM_BYT_CSR_VECTOR_SEL |
345 				  SHIM_BYT_CSR_STALL,
346 				  SHIM_BYT_CSR_RST | SHIM_BYT_CSR_VECTOR_SEL |
347 				  SHIM_BYT_CSR_STALL);
348 
349 	usleep_range(10, 15);
350 
351 	/* take DSP out of reset and keep stalled for FW loading */
352 	snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_CSR,
353 				  SHIM_BYT_CSR_RST, 0);
354 
355 	return 0;
356 }
357 
358 /* Baytrail DAIs */
359 static struct snd_soc_dai_driver byt_dai[] = {
360 {
361 	.name = "ssp0-port",
362 },
363 {
364 	.name = "ssp1-port",
365 },
366 {
367 	.name = "ssp2-port",
368 },
369 {
370 	.name = "ssp3-port",
371 },
372 {
373 	.name = "ssp4-port",
374 },
375 {
376 	.name = "ssp5-port",
377 },
378 };
379 
380 /*
381  * Probe and remove.
382  */
383 
384 #if IS_ENABLED(CONFIG_SND_SOC_SOF_MERRIFIELD)
385 
386 static int tangier_pci_probe(struct snd_sof_dev *sdev)
387 {
388 	struct snd_sof_pdata *pdata = sdev->pdata;
389 	const struct sof_dev_desc *desc = pdata->desc;
390 	struct pci_dev *pci = to_pci_dev(sdev->dev);
391 	u32 base, size;
392 	int ret;
393 
394 	/* DSP DMA can only access low 31 bits of host memory */
395 	ret = dma_coerce_mask_and_coherent(&pci->dev, DMA_BIT_MASK(31));
396 	if (ret < 0) {
397 		dev_err(sdev->dev, "error: failed to set DMA mask %d\n", ret);
398 		return ret;
399 	}
400 
401 	/* LPE base */
402 	base = pci_resource_start(pci, desc->resindex_lpe_base) - IRAM_OFFSET;
403 	size = BYT_PCI_BAR_SIZE;
404 
405 	dev_dbg(sdev->dev, "LPE PHY base at 0x%x size 0x%x", base, size);
406 	sdev->bar[BYT_DSP_BAR] = devm_ioremap(sdev->dev, base, size);
407 	if (!sdev->bar[BYT_DSP_BAR]) {
408 		dev_err(sdev->dev, "error: failed to ioremap LPE base 0x%x size 0x%x\n",
409 			base, size);
410 		return -ENODEV;
411 	}
412 	dev_dbg(sdev->dev, "LPE VADDR %p\n", sdev->bar[BYT_DSP_BAR]);
413 
414 	/* IMR base - optional */
415 	if (desc->resindex_imr_base == -1)
416 		goto irq;
417 
418 	base = pci_resource_start(pci, desc->resindex_imr_base);
419 	size = pci_resource_len(pci, desc->resindex_imr_base);
420 
421 	/* some BIOSes don't map IMR */
422 	if (base == 0x55aa55aa || base == 0x0) {
423 		dev_info(sdev->dev, "IMR not set by BIOS. Ignoring\n");
424 		goto irq;
425 	}
426 
427 	dev_dbg(sdev->dev, "IMR base at 0x%x size 0x%x", base, size);
428 	sdev->bar[BYT_IMR_BAR] = devm_ioremap(sdev->dev, base, size);
429 	if (!sdev->bar[BYT_IMR_BAR]) {
430 		dev_err(sdev->dev, "error: failed to ioremap IMR base 0x%x size 0x%x\n",
431 			base, size);
432 		return -ENODEV;
433 	}
434 	dev_dbg(sdev->dev, "IMR VADDR %p\n", sdev->bar[BYT_IMR_BAR]);
435 
436 irq:
437 	/* register our IRQ */
438 	sdev->ipc_irq = pci->irq;
439 	dev_dbg(sdev->dev, "using IRQ %d\n", sdev->ipc_irq);
440 	ret = devm_request_threaded_irq(sdev->dev, sdev->ipc_irq,
441 					byt_irq_handler, byt_irq_thread,
442 					0, "AudioDSP", sdev);
443 	if (ret < 0) {
444 		dev_err(sdev->dev, "error: failed to register IRQ %d\n",
445 			sdev->ipc_irq);
446 		return ret;
447 	}
448 
449 	/* enable Interrupt from both sides */
450 	snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRX, 0x3, 0x0);
451 	snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRD, 0x3, 0x0);
452 
453 	/* set default mailbox offset for FW ready message */
454 	sdev->dsp_box.offset = MBOX_OFFSET;
455 
456 	return ret;
457 }
458 
459 const struct snd_sof_dsp_ops sof_tng_ops = {
460 	/* device init */
461 	.probe		= tangier_pci_probe,
462 
463 	/* DSP core boot / reset */
464 	.run		= byt_run,
465 	.reset		= byt_reset,
466 
467 	/* Register IO */
468 	.write		= sof_io_write,
469 	.read		= sof_io_read,
470 	.write64	= sof_io_write64,
471 	.read64		= sof_io_read64,
472 
473 	/* Block IO */
474 	.block_read	= sof_block_read,
475 	.block_write	= sof_block_write,
476 
477 	/* doorbell */
478 	.irq_handler	= byt_irq_handler,
479 	.irq_thread	= byt_irq_thread,
480 
481 	/* ipc */
482 	.send_msg	= byt_send_msg,
483 	.fw_ready	= sof_fw_ready,
484 	.get_mailbox_offset = byt_get_mailbox_offset,
485 	.get_window_offset = byt_get_window_offset,
486 
487 	.ipc_msg_data	= intel_ipc_msg_data,
488 	.ipc_pcm_params	= intel_ipc_pcm_params,
489 
490 	/* debug */
491 	.debug_map	= byt_debugfs,
492 	.debug_map_count	= ARRAY_SIZE(byt_debugfs),
493 	.dbg_dump	= byt_dump,
494 
495 	/* stream callbacks */
496 	.pcm_open	= intel_pcm_open,
497 	.pcm_close	= intel_pcm_close,
498 
499 	/* module loading */
500 	.load_module	= snd_sof_parse_module_memcpy,
501 
502 	/*Firmware loading */
503 	.load_firmware	= snd_sof_load_firmware_memcpy,
504 
505 	/* DAI drivers */
506 	.drv = byt_dai,
507 	.num_drv = 3, /* we have only 3 SSPs on byt*/
508 };
509 EXPORT_SYMBOL(sof_tng_ops);
510 
511 const struct sof_intel_dsp_desc tng_chip_info = {
512 	.cores_num = 1,
513 	.cores_mask = 1,
514 };
515 EXPORT_SYMBOL(tng_chip_info);
516 
517 #endif /* CONFIG_SND_SOC_SOF_MERRIFIELD */
518 
519 #if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL)
520 
521 static int byt_acpi_probe(struct snd_sof_dev *sdev)
522 {
523 	struct snd_sof_pdata *pdata = sdev->pdata;
524 	const struct sof_dev_desc *desc = pdata->desc;
525 	struct platform_device *pdev =
526 		container_of(sdev->dev, struct platform_device, dev);
527 	struct resource *mmio;
528 	u32 base, size;
529 	int ret;
530 
531 	/* DSP DMA can only access low 31 bits of host memory */
532 	ret = dma_coerce_mask_and_coherent(sdev->dev, DMA_BIT_MASK(31));
533 	if (ret < 0) {
534 		dev_err(sdev->dev, "error: failed to set DMA mask %d\n", ret);
535 		return ret;
536 	}
537 
538 	/* LPE base */
539 	mmio = platform_get_resource(pdev, IORESOURCE_MEM,
540 				     desc->resindex_lpe_base);
541 	if (mmio) {
542 		base = mmio->start;
543 		size = resource_size(mmio);
544 	} else {
545 		dev_err(sdev->dev, "error: failed to get LPE base at idx %d\n",
546 			desc->resindex_lpe_base);
547 		return -EINVAL;
548 	}
549 
550 	dev_dbg(sdev->dev, "LPE PHY base at 0x%x size 0x%x", base, size);
551 	sdev->bar[BYT_DSP_BAR] = devm_ioremap(sdev->dev, base, size);
552 	if (!sdev->bar[BYT_DSP_BAR]) {
553 		dev_err(sdev->dev, "error: failed to ioremap LPE base 0x%x size 0x%x\n",
554 			base, size);
555 		return -ENODEV;
556 	}
557 	dev_dbg(sdev->dev, "LPE VADDR %p\n", sdev->bar[BYT_DSP_BAR]);
558 
559 	/* TODO: add offsets */
560 	sdev->mmio_bar = BYT_DSP_BAR;
561 	sdev->mailbox_bar = BYT_DSP_BAR;
562 
563 	/* IMR base - optional */
564 	if (desc->resindex_imr_base == -1)
565 		goto irq;
566 
567 	mmio = platform_get_resource(pdev, IORESOURCE_MEM,
568 				     desc->resindex_imr_base);
569 	if (mmio) {
570 		base = mmio->start;
571 		size = resource_size(mmio);
572 	} else {
573 		dev_err(sdev->dev, "error: failed to get IMR base at idx %d\n",
574 			desc->resindex_imr_base);
575 		return -ENODEV;
576 	}
577 
578 	/* some BIOSes don't map IMR */
579 	if (base == 0x55aa55aa || base == 0x0) {
580 		dev_info(sdev->dev, "IMR not set by BIOS. Ignoring\n");
581 		goto irq;
582 	}
583 
584 	dev_dbg(sdev->dev, "IMR base at 0x%x size 0x%x", base, size);
585 	sdev->bar[BYT_IMR_BAR] = devm_ioremap(sdev->dev, base, size);
586 	if (!sdev->bar[BYT_IMR_BAR]) {
587 		dev_err(sdev->dev, "error: failed to ioremap IMR base 0x%x size 0x%x\n",
588 			base, size);
589 		return -ENODEV;
590 	}
591 	dev_dbg(sdev->dev, "IMR VADDR %p\n", sdev->bar[BYT_IMR_BAR]);
592 
593 irq:
594 	/* register our IRQ */
595 	sdev->ipc_irq = platform_get_irq(pdev, desc->irqindex_host_ipc);
596 	if (sdev->ipc_irq < 0)
597 		return sdev->ipc_irq;
598 
599 	dev_dbg(sdev->dev, "using IRQ %d\n", sdev->ipc_irq);
600 	ret = devm_request_threaded_irq(sdev->dev, sdev->ipc_irq,
601 					byt_irq_handler, byt_irq_thread,
602 					IRQF_SHARED, "AudioDSP", sdev);
603 	if (ret < 0) {
604 		dev_err(sdev->dev, "error: failed to register IRQ %d\n",
605 			sdev->ipc_irq);
606 		return ret;
607 	}
608 
609 	/* enable Interrupt from both sides */
610 	snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRX, 0x3, 0x0);
611 	snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRD, 0x3, 0x0);
612 
613 	/* set default mailbox offset for FW ready message */
614 	sdev->dsp_box.offset = MBOX_OFFSET;
615 
616 	return ret;
617 }
618 
619 /* baytrail ops */
620 const struct snd_sof_dsp_ops sof_byt_ops = {
621 	/* device init */
622 	.probe		= byt_acpi_probe,
623 
624 	/* DSP core boot / reset */
625 	.run		= byt_run,
626 	.reset		= byt_reset,
627 
628 	/* Register IO */
629 	.write		= sof_io_write,
630 	.read		= sof_io_read,
631 	.write64	= sof_io_write64,
632 	.read64		= sof_io_read64,
633 
634 	/* Block IO */
635 	.block_read	= sof_block_read,
636 	.block_write	= sof_block_write,
637 
638 	/* doorbell */
639 	.irq_handler	= byt_irq_handler,
640 	.irq_thread	= byt_irq_thread,
641 
642 	/* ipc */
643 	.send_msg	= byt_send_msg,
644 	.fw_ready	= sof_fw_ready,
645 	.get_mailbox_offset = byt_get_mailbox_offset,
646 	.get_window_offset = byt_get_window_offset,
647 
648 	.ipc_msg_data	= intel_ipc_msg_data,
649 	.ipc_pcm_params	= intel_ipc_pcm_params,
650 
651 	/* debug */
652 	.debug_map	= byt_debugfs,
653 	.debug_map_count	= ARRAY_SIZE(byt_debugfs),
654 	.dbg_dump	= byt_dump,
655 
656 	/* stream callbacks */
657 	.pcm_open	= intel_pcm_open,
658 	.pcm_close	= intel_pcm_close,
659 
660 	/* module loading */
661 	.load_module	= snd_sof_parse_module_memcpy,
662 
663 	/*Firmware loading */
664 	.load_firmware	= snd_sof_load_firmware_memcpy,
665 
666 	/* DAI drivers */
667 	.drv = byt_dai,
668 	.num_drv = 3, /* we have only 3 SSPs on byt*/
669 };
670 EXPORT_SYMBOL(sof_byt_ops);
671 
672 const struct sof_intel_dsp_desc byt_chip_info = {
673 	.cores_num = 1,
674 	.cores_mask = 1,
675 };
676 EXPORT_SYMBOL(byt_chip_info);
677 
678 /* cherrytrail and braswell ops */
679 const struct snd_sof_dsp_ops sof_cht_ops = {
680 	/* device init */
681 	.probe		= byt_acpi_probe,
682 
683 	/* DSP core boot / reset */
684 	.run		= byt_run,
685 	.reset		= byt_reset,
686 
687 	/* Register IO */
688 	.write		= sof_io_write,
689 	.read		= sof_io_read,
690 	.write64	= sof_io_write64,
691 	.read64		= sof_io_read64,
692 
693 	/* Block IO */
694 	.block_read	= sof_block_read,
695 	.block_write	= sof_block_write,
696 
697 	/* doorbell */
698 	.irq_handler	= byt_irq_handler,
699 	.irq_thread	= byt_irq_thread,
700 
701 	/* ipc */
702 	.send_msg	= byt_send_msg,
703 	.fw_ready	= sof_fw_ready,
704 	.get_mailbox_offset = byt_get_mailbox_offset,
705 	.get_window_offset = byt_get_window_offset,
706 
707 	.ipc_msg_data	= intel_ipc_msg_data,
708 	.ipc_pcm_params	= intel_ipc_pcm_params,
709 
710 	/* debug */
711 	.debug_map	= cht_debugfs,
712 	.debug_map_count	= ARRAY_SIZE(cht_debugfs),
713 	.dbg_dump	= byt_dump,
714 
715 	/* stream callbacks */
716 	.pcm_open	= intel_pcm_open,
717 	.pcm_close	= intel_pcm_close,
718 
719 	/* module loading */
720 	.load_module	= snd_sof_parse_module_memcpy,
721 
722 	/*Firmware loading */
723 	.load_firmware	= snd_sof_load_firmware_memcpy,
724 
725 	/* DAI drivers */
726 	.drv = byt_dai,
727 	/* all 6 SSPs may be available for cherrytrail */
728 	.num_drv = ARRAY_SIZE(byt_dai),
729 };
730 EXPORT_SYMBOL(sof_cht_ops);
731 
732 const struct sof_intel_dsp_desc cht_chip_info = {
733 	.cores_num = 1,
734 	.cores_mask = 1,
735 };
736 EXPORT_SYMBOL(cht_chip_info);
737 
738 #endif /* CONFIG_SND_SOC_SOF_BAYTRAIL */
739 
740 MODULE_LICENSE("Dual BSD/GPL");
741