18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
28c2ecf20Sopenharmony_ci//
38c2ecf20Sopenharmony_ci// This file is provided under a dual BSD/GPLv2 license.  When using or
48c2ecf20Sopenharmony_ci// redistributing this file, you may do so under either license.
58c2ecf20Sopenharmony_ci//
68c2ecf20Sopenharmony_ci// Copyright(c) 2018 Intel Corporation. All rights reserved.
78c2ecf20Sopenharmony_ci//
88c2ecf20Sopenharmony_ci// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
98c2ecf20Sopenharmony_ci//
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci/*
128c2ecf20Sopenharmony_ci * Hardware interface for audio DSP on Broadwell
138c2ecf20Sopenharmony_ci */
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci#include <linux/module.h>
168c2ecf20Sopenharmony_ci#include <sound/sof.h>
178c2ecf20Sopenharmony_ci#include <sound/sof/xtensa.h>
188c2ecf20Sopenharmony_ci#include "../ops.h"
198c2ecf20Sopenharmony_ci#include "shim.h"
208c2ecf20Sopenharmony_ci#include "../sof-audio.h"
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci/* BARs */
238c2ecf20Sopenharmony_ci#define BDW_DSP_BAR 0
248c2ecf20Sopenharmony_ci#define BDW_PCI_BAR 1
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci/*
278c2ecf20Sopenharmony_ci * Debug
288c2ecf20Sopenharmony_ci */
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci/* DSP memories for BDW */
318c2ecf20Sopenharmony_ci#define IRAM_OFFSET     0xA0000
328c2ecf20Sopenharmony_ci#define BDW_IRAM_SIZE       (10 * 32 * 1024)
338c2ecf20Sopenharmony_ci#define DRAM_OFFSET     0x00000
348c2ecf20Sopenharmony_ci#define BDW_DRAM_SIZE       (20 * 32 * 1024)
358c2ecf20Sopenharmony_ci#define SHIM_OFFSET     0xFB000
368c2ecf20Sopenharmony_ci#define SHIM_SIZE       0x100
378c2ecf20Sopenharmony_ci#define MBOX_OFFSET     0x9E000
388c2ecf20Sopenharmony_ci#define MBOX_SIZE       0x1000
398c2ecf20Sopenharmony_ci#define MBOX_DUMP_SIZE 0x30
408c2ecf20Sopenharmony_ci#define EXCEPT_OFFSET	0x800
418c2ecf20Sopenharmony_ci#define EXCEPT_MAX_HDR_SIZE	0x400
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci/* DSP peripherals */
448c2ecf20Sopenharmony_ci#define DMAC0_OFFSET    0xFE000
458c2ecf20Sopenharmony_ci#define DMAC1_OFFSET    0xFF000
468c2ecf20Sopenharmony_ci#define DMAC_SIZE       0x420
478c2ecf20Sopenharmony_ci#define SSP0_OFFSET     0xFC000
488c2ecf20Sopenharmony_ci#define SSP1_OFFSET     0xFD000
498c2ecf20Sopenharmony_ci#define SSP_SIZE	0x100
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci#define BDW_STACK_DUMP_SIZE	32
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci#define BDW_PANIC_OFFSET(x)	((x) & 0xFFFF)
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_cistatic const struct snd_sof_debugfs_map bdw_debugfs[] = {
568c2ecf20Sopenharmony_ci	{"dmac0", BDW_DSP_BAR, DMAC0_OFFSET, DMAC_SIZE,
578c2ecf20Sopenharmony_ci	 SOF_DEBUGFS_ACCESS_ALWAYS},
588c2ecf20Sopenharmony_ci	{"dmac1", BDW_DSP_BAR, DMAC1_OFFSET, DMAC_SIZE,
598c2ecf20Sopenharmony_ci	 SOF_DEBUGFS_ACCESS_ALWAYS},
608c2ecf20Sopenharmony_ci	{"ssp0", BDW_DSP_BAR, SSP0_OFFSET, SSP_SIZE,
618c2ecf20Sopenharmony_ci	 SOF_DEBUGFS_ACCESS_ALWAYS},
628c2ecf20Sopenharmony_ci	{"ssp1", BDW_DSP_BAR, SSP1_OFFSET, SSP_SIZE,
638c2ecf20Sopenharmony_ci	 SOF_DEBUGFS_ACCESS_ALWAYS},
648c2ecf20Sopenharmony_ci	{"iram", BDW_DSP_BAR, IRAM_OFFSET, BDW_IRAM_SIZE,
658c2ecf20Sopenharmony_ci	 SOF_DEBUGFS_ACCESS_D0_ONLY},
668c2ecf20Sopenharmony_ci	{"dram", BDW_DSP_BAR, DRAM_OFFSET, BDW_DRAM_SIZE,
678c2ecf20Sopenharmony_ci	 SOF_DEBUGFS_ACCESS_D0_ONLY},
688c2ecf20Sopenharmony_ci	{"shim", BDW_DSP_BAR, SHIM_OFFSET, SHIM_SIZE,
698c2ecf20Sopenharmony_ci	 SOF_DEBUGFS_ACCESS_ALWAYS},
708c2ecf20Sopenharmony_ci};
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_cistatic void bdw_host_done(struct snd_sof_dev *sdev);
738c2ecf20Sopenharmony_cistatic void bdw_dsp_done(struct snd_sof_dev *sdev);
748c2ecf20Sopenharmony_cistatic void bdw_get_reply(struct snd_sof_dev *sdev);
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci/*
778c2ecf20Sopenharmony_ci * DSP Control.
788c2ecf20Sopenharmony_ci */
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_cistatic int bdw_run(struct snd_sof_dev *sdev)
818c2ecf20Sopenharmony_ci{
828c2ecf20Sopenharmony_ci	/* set opportunistic mode on engine 0,1 for all channels */
838c2ecf20Sopenharmony_ci	snd_sof_dsp_update_bits(sdev, BDW_DSP_BAR, SHIM_HMDC,
848c2ecf20Sopenharmony_ci				SHIM_HMDC_HDDA_E0_ALLCH |
858c2ecf20Sopenharmony_ci				SHIM_HMDC_HDDA_E1_ALLCH, 0);
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci	/* set DSP to RUN */
888c2ecf20Sopenharmony_ci	snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_CSR,
898c2ecf20Sopenharmony_ci					 SHIM_CSR_STALL, 0x0);
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci	/* return init core mask */
928c2ecf20Sopenharmony_ci	return 1;
938c2ecf20Sopenharmony_ci}
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_cistatic int bdw_reset(struct snd_sof_dev *sdev)
968c2ecf20Sopenharmony_ci{
978c2ecf20Sopenharmony_ci	/* put DSP into reset and stall */
988c2ecf20Sopenharmony_ci	snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_CSR,
998c2ecf20Sopenharmony_ci					 SHIM_CSR_RST | SHIM_CSR_STALL,
1008c2ecf20Sopenharmony_ci					 SHIM_CSR_RST | SHIM_CSR_STALL);
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ci	/* keep in reset for 10ms */
1038c2ecf20Sopenharmony_ci	mdelay(10);
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci	/* take DSP out of reset and keep stalled for FW loading */
1068c2ecf20Sopenharmony_ci	snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_CSR,
1078c2ecf20Sopenharmony_ci					 SHIM_CSR_RST | SHIM_CSR_STALL,
1088c2ecf20Sopenharmony_ci					 SHIM_CSR_STALL);
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci	return 0;
1118c2ecf20Sopenharmony_ci}
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_cistatic int bdw_set_dsp_D0(struct snd_sof_dev *sdev)
1148c2ecf20Sopenharmony_ci{
1158c2ecf20Sopenharmony_ci	int tries = 10;
1168c2ecf20Sopenharmony_ci	u32 reg;
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_ci	/* Disable core clock gating (VDRTCTL2.DCLCGE = 0) */
1198c2ecf20Sopenharmony_ci	snd_sof_dsp_update_bits_unlocked(sdev, BDW_PCI_BAR, PCI_VDRTCTL2,
1208c2ecf20Sopenharmony_ci					 PCI_VDRTCL2_DCLCGE |
1218c2ecf20Sopenharmony_ci					 PCI_VDRTCL2_DTCGE, 0);
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ci	/* Disable D3PG (VDRTCTL0.D3PGD = 1) */
1248c2ecf20Sopenharmony_ci	snd_sof_dsp_update_bits_unlocked(sdev, BDW_PCI_BAR, PCI_VDRTCTL0,
1258c2ecf20Sopenharmony_ci					 PCI_VDRTCL0_D3PGD, PCI_VDRTCL0_D3PGD);
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci	/* Set D0 state */
1288c2ecf20Sopenharmony_ci	snd_sof_dsp_update_bits_unlocked(sdev, BDW_PCI_BAR, PCI_PMCS,
1298c2ecf20Sopenharmony_ci					 PCI_PMCS_PS_MASK, 0);
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci	/* check that ADSP shim is enabled */
1328c2ecf20Sopenharmony_ci	while (tries--) {
1338c2ecf20Sopenharmony_ci		reg = readl(sdev->bar[BDW_PCI_BAR] + PCI_PMCS)
1348c2ecf20Sopenharmony_ci			& PCI_PMCS_PS_MASK;
1358c2ecf20Sopenharmony_ci		if (reg == 0)
1368c2ecf20Sopenharmony_ci			goto finish;
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_ci		msleep(20);
1398c2ecf20Sopenharmony_ci	}
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_ci	return -ENODEV;
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_cifinish:
1448c2ecf20Sopenharmony_ci	/*
1458c2ecf20Sopenharmony_ci	 * select SSP1 19.2MHz base clock, SSP clock 0,
1468c2ecf20Sopenharmony_ci	 * turn off Low Power Clock
1478c2ecf20Sopenharmony_ci	 */
1488c2ecf20Sopenharmony_ci	snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_CSR,
1498c2ecf20Sopenharmony_ci					 SHIM_CSR_S1IOCS | SHIM_CSR_SBCS1 |
1508c2ecf20Sopenharmony_ci					 SHIM_CSR_LPCS, 0x0);
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci	/* stall DSP core, set clk to 192/96Mhz */
1538c2ecf20Sopenharmony_ci	snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR,
1548c2ecf20Sopenharmony_ci					 SHIM_CSR, SHIM_CSR_STALL |
1558c2ecf20Sopenharmony_ci					 SHIM_CSR_DCS_MASK,
1568c2ecf20Sopenharmony_ci					 SHIM_CSR_STALL |
1578c2ecf20Sopenharmony_ci					 SHIM_CSR_DCS(4));
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_ci	/* Set 24MHz MCLK, prevent local clock gating, enable SSP0 clock */
1608c2ecf20Sopenharmony_ci	snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_CLKCTL,
1618c2ecf20Sopenharmony_ci					 SHIM_CLKCTL_MASK |
1628c2ecf20Sopenharmony_ci					 SHIM_CLKCTL_DCPLCG |
1638c2ecf20Sopenharmony_ci					 SHIM_CLKCTL_SCOE0,
1648c2ecf20Sopenharmony_ci					 SHIM_CLKCTL_MASK |
1658c2ecf20Sopenharmony_ci					 SHIM_CLKCTL_DCPLCG |
1668c2ecf20Sopenharmony_ci					 SHIM_CLKCTL_SCOE0);
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_ci	/* Stall and reset core, set CSR */
1698c2ecf20Sopenharmony_ci	bdw_reset(sdev);
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ci	/* Enable core clock gating (VDRTCTL2.DCLCGE = 1), delay 50 us */
1728c2ecf20Sopenharmony_ci	snd_sof_dsp_update_bits_unlocked(sdev, BDW_PCI_BAR, PCI_VDRTCTL2,
1738c2ecf20Sopenharmony_ci					 PCI_VDRTCL2_DCLCGE |
1748c2ecf20Sopenharmony_ci					 PCI_VDRTCL2_DTCGE,
1758c2ecf20Sopenharmony_ci					 PCI_VDRTCL2_DCLCGE |
1768c2ecf20Sopenharmony_ci					 PCI_VDRTCL2_DTCGE);
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_ci	usleep_range(50, 55);
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_ci	/* switch on audio PLL */
1818c2ecf20Sopenharmony_ci	snd_sof_dsp_update_bits_unlocked(sdev, BDW_PCI_BAR, PCI_VDRTCTL2,
1828c2ecf20Sopenharmony_ci					 PCI_VDRTCL2_APLLSE_MASK, 0);
1838c2ecf20Sopenharmony_ci
1848c2ecf20Sopenharmony_ci	/*
1858c2ecf20Sopenharmony_ci	 * set default power gating control, enable power gating control for
1868c2ecf20Sopenharmony_ci	 * all blocks. that is, can't be accessed, please enable each block
1878c2ecf20Sopenharmony_ci	 * before accessing.
1888c2ecf20Sopenharmony_ci	 */
1898c2ecf20Sopenharmony_ci	snd_sof_dsp_update_bits_unlocked(sdev, BDW_PCI_BAR, PCI_VDRTCTL0,
1908c2ecf20Sopenharmony_ci					 0xfffffffC, 0x0);
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ci	/* disable DMA finish function for SSP0 & SSP1 */
1938c2ecf20Sopenharmony_ci	snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR,  SHIM_CSR2,
1948c2ecf20Sopenharmony_ci					 SHIM_CSR2_SDFD_SSP1,
1958c2ecf20Sopenharmony_ci					 SHIM_CSR2_SDFD_SSP1);
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_ci	/* set on-demond mode on engine 0,1 for all channels */
1988c2ecf20Sopenharmony_ci	snd_sof_dsp_update_bits(sdev, BDW_DSP_BAR, SHIM_HMDC,
1998c2ecf20Sopenharmony_ci				SHIM_HMDC_HDDA_E0_ALLCH |
2008c2ecf20Sopenharmony_ci				SHIM_HMDC_HDDA_E1_ALLCH,
2018c2ecf20Sopenharmony_ci				SHIM_HMDC_HDDA_E0_ALLCH |
2028c2ecf20Sopenharmony_ci				SHIM_HMDC_HDDA_E1_ALLCH);
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_ci	/* Enable Interrupt from both sides */
2058c2ecf20Sopenharmony_ci	snd_sof_dsp_update_bits(sdev, BDW_DSP_BAR, SHIM_IMRX,
2068c2ecf20Sopenharmony_ci				(SHIM_IMRX_BUSY | SHIM_IMRX_DONE), 0x0);
2078c2ecf20Sopenharmony_ci	snd_sof_dsp_update_bits(sdev, BDW_DSP_BAR, SHIM_IMRD,
2088c2ecf20Sopenharmony_ci				(SHIM_IMRD_DONE | SHIM_IMRD_BUSY |
2098c2ecf20Sopenharmony_ci				SHIM_IMRD_SSP0 | SHIM_IMRD_DMAC), 0x0);
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_ci	/* clear IPC registers */
2128c2ecf20Sopenharmony_ci	snd_sof_dsp_write(sdev, BDW_DSP_BAR, SHIM_IPCX, 0x0);
2138c2ecf20Sopenharmony_ci	snd_sof_dsp_write(sdev, BDW_DSP_BAR, SHIM_IPCD, 0x0);
2148c2ecf20Sopenharmony_ci	snd_sof_dsp_write(sdev, BDW_DSP_BAR, 0x80, 0x6);
2158c2ecf20Sopenharmony_ci	snd_sof_dsp_write(sdev, BDW_DSP_BAR, 0xe0, 0x300a);
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci	return 0;
2188c2ecf20Sopenharmony_ci}
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_cistatic void bdw_get_registers(struct snd_sof_dev *sdev,
2218c2ecf20Sopenharmony_ci			      struct sof_ipc_dsp_oops_xtensa *xoops,
2228c2ecf20Sopenharmony_ci			      struct sof_ipc_panic_info *panic_info,
2238c2ecf20Sopenharmony_ci			      u32 *stack, size_t stack_words)
2248c2ecf20Sopenharmony_ci{
2258c2ecf20Sopenharmony_ci	u32 offset = sdev->dsp_oops_offset;
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_ci	/* first read registers */
2288c2ecf20Sopenharmony_ci	sof_mailbox_read(sdev, offset, xoops, sizeof(*xoops));
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_ci	/* note: variable AR register array is not read */
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_ci	/* then get panic info */
2338c2ecf20Sopenharmony_ci	if (xoops->arch_hdr.totalsize > EXCEPT_MAX_HDR_SIZE) {
2348c2ecf20Sopenharmony_ci		dev_err(sdev->dev, "invalid header size 0x%x. FW oops is bogus\n",
2358c2ecf20Sopenharmony_ci			xoops->arch_hdr.totalsize);
2368c2ecf20Sopenharmony_ci		return;
2378c2ecf20Sopenharmony_ci	}
2388c2ecf20Sopenharmony_ci	offset += xoops->arch_hdr.totalsize;
2398c2ecf20Sopenharmony_ci	sof_mailbox_read(sdev, offset, panic_info, sizeof(*panic_info));
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_ci	/* then get the stack */
2428c2ecf20Sopenharmony_ci	offset += sizeof(*panic_info);
2438c2ecf20Sopenharmony_ci	sof_mailbox_read(sdev, offset, stack, stack_words * sizeof(u32));
2448c2ecf20Sopenharmony_ci}
2458c2ecf20Sopenharmony_ci
2468c2ecf20Sopenharmony_cistatic void bdw_dump(struct snd_sof_dev *sdev, u32 flags)
2478c2ecf20Sopenharmony_ci{
2488c2ecf20Sopenharmony_ci	struct sof_ipc_dsp_oops_xtensa xoops;
2498c2ecf20Sopenharmony_ci	struct sof_ipc_panic_info panic_info;
2508c2ecf20Sopenharmony_ci	u32 stack[BDW_STACK_DUMP_SIZE];
2518c2ecf20Sopenharmony_ci	u32 status, panic, imrx, imrd;
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_ci	/* now try generic SOF status messages */
2548c2ecf20Sopenharmony_ci	status = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_IPCD);
2558c2ecf20Sopenharmony_ci	panic = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_IPCX);
2568c2ecf20Sopenharmony_ci	bdw_get_registers(sdev, &xoops, &panic_info, stack,
2578c2ecf20Sopenharmony_ci			  BDW_STACK_DUMP_SIZE);
2588c2ecf20Sopenharmony_ci	snd_sof_get_status(sdev, status, panic, &xoops, &panic_info, stack,
2598c2ecf20Sopenharmony_ci			   BDW_STACK_DUMP_SIZE);
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ci	/* provide some context for firmware debug */
2628c2ecf20Sopenharmony_ci	imrx = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_IMRX);
2638c2ecf20Sopenharmony_ci	imrd = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_IMRD);
2648c2ecf20Sopenharmony_ci	dev_err(sdev->dev,
2658c2ecf20Sopenharmony_ci		"error: ipc host -> DSP: pending %s complete %s raw 0x%8.8x\n",
2668c2ecf20Sopenharmony_ci		(panic & SHIM_IPCX_BUSY) ? "yes" : "no",
2678c2ecf20Sopenharmony_ci		(panic & SHIM_IPCX_DONE) ? "yes" : "no", panic);
2688c2ecf20Sopenharmony_ci	dev_err(sdev->dev,
2698c2ecf20Sopenharmony_ci		"error: mask host: pending %s complete %s raw 0x%8.8x\n",
2708c2ecf20Sopenharmony_ci		(imrx & SHIM_IMRX_BUSY) ? "yes" : "no",
2718c2ecf20Sopenharmony_ci		(imrx & SHIM_IMRX_DONE) ? "yes" : "no", imrx);
2728c2ecf20Sopenharmony_ci	dev_err(sdev->dev,
2738c2ecf20Sopenharmony_ci		"error: ipc DSP -> host: pending %s complete %s raw 0x%8.8x\n",
2748c2ecf20Sopenharmony_ci		(status & SHIM_IPCD_BUSY) ? "yes" : "no",
2758c2ecf20Sopenharmony_ci		(status & SHIM_IPCD_DONE) ? "yes" : "no", status);
2768c2ecf20Sopenharmony_ci	dev_err(sdev->dev,
2778c2ecf20Sopenharmony_ci		"error: mask DSP: pending %s complete %s raw 0x%8.8x\n",
2788c2ecf20Sopenharmony_ci		(imrd & SHIM_IMRD_BUSY) ? "yes" : "no",
2798c2ecf20Sopenharmony_ci		(imrd & SHIM_IMRD_DONE) ? "yes" : "no", imrd);
2808c2ecf20Sopenharmony_ci}
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_ci/*
2838c2ecf20Sopenharmony_ci * IPC Doorbell IRQ handler and thread.
2848c2ecf20Sopenharmony_ci */
2858c2ecf20Sopenharmony_ci
2868c2ecf20Sopenharmony_cistatic irqreturn_t bdw_irq_handler(int irq, void *context)
2878c2ecf20Sopenharmony_ci{
2888c2ecf20Sopenharmony_ci	struct snd_sof_dev *sdev = context;
2898c2ecf20Sopenharmony_ci	u32 isr;
2908c2ecf20Sopenharmony_ci	int ret = IRQ_NONE;
2918c2ecf20Sopenharmony_ci
2928c2ecf20Sopenharmony_ci	/* Interrupt arrived, check src */
2938c2ecf20Sopenharmony_ci	isr = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_ISRX);
2948c2ecf20Sopenharmony_ci	if (isr & (SHIM_ISRX_DONE | SHIM_ISRX_BUSY))
2958c2ecf20Sopenharmony_ci		ret = IRQ_WAKE_THREAD;
2968c2ecf20Sopenharmony_ci
2978c2ecf20Sopenharmony_ci	return ret;
2988c2ecf20Sopenharmony_ci}
2998c2ecf20Sopenharmony_ci
3008c2ecf20Sopenharmony_cistatic irqreturn_t bdw_irq_thread(int irq, void *context)
3018c2ecf20Sopenharmony_ci{
3028c2ecf20Sopenharmony_ci	struct snd_sof_dev *sdev = context;
3038c2ecf20Sopenharmony_ci	u32 ipcx, ipcd, imrx;
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_ci	imrx = snd_sof_dsp_read64(sdev, BDW_DSP_BAR, SHIM_IMRX);
3068c2ecf20Sopenharmony_ci	ipcx = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_IPCX);
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_ci	/* reply message from DSP */
3098c2ecf20Sopenharmony_ci	if (ipcx & SHIM_IPCX_DONE &&
3108c2ecf20Sopenharmony_ci	    !(imrx & SHIM_IMRX_DONE)) {
3118c2ecf20Sopenharmony_ci		/* Mask Done interrupt before return */
3128c2ecf20Sopenharmony_ci		snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR,
3138c2ecf20Sopenharmony_ci						 SHIM_IMRX, SHIM_IMRX_DONE,
3148c2ecf20Sopenharmony_ci						 SHIM_IMRX_DONE);
3158c2ecf20Sopenharmony_ci
3168c2ecf20Sopenharmony_ci		spin_lock_irq(&sdev->ipc_lock);
3178c2ecf20Sopenharmony_ci
3188c2ecf20Sopenharmony_ci		/*
3198c2ecf20Sopenharmony_ci		 * handle immediate reply from DSP core. If the msg is
3208c2ecf20Sopenharmony_ci		 * found, set done bit in cmd_done which is called at the
3218c2ecf20Sopenharmony_ci		 * end of message processing function, else set it here
3228c2ecf20Sopenharmony_ci		 * because the done bit can't be set in cmd_done function
3238c2ecf20Sopenharmony_ci		 * which is triggered by msg
3248c2ecf20Sopenharmony_ci		 */
3258c2ecf20Sopenharmony_ci		bdw_get_reply(sdev);
3268c2ecf20Sopenharmony_ci		snd_sof_ipc_reply(sdev, ipcx);
3278c2ecf20Sopenharmony_ci
3288c2ecf20Sopenharmony_ci		bdw_dsp_done(sdev);
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_ci		spin_unlock_irq(&sdev->ipc_lock);
3318c2ecf20Sopenharmony_ci	}
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_ci	ipcd = snd_sof_dsp_read(sdev, BDW_DSP_BAR, SHIM_IPCD);
3348c2ecf20Sopenharmony_ci
3358c2ecf20Sopenharmony_ci	/* new message from DSP */
3368c2ecf20Sopenharmony_ci	if (ipcd & SHIM_IPCD_BUSY &&
3378c2ecf20Sopenharmony_ci	    !(imrx & SHIM_IMRX_BUSY)) {
3388c2ecf20Sopenharmony_ci		/* Mask Busy interrupt before return */
3398c2ecf20Sopenharmony_ci		snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR,
3408c2ecf20Sopenharmony_ci						 SHIM_IMRX, SHIM_IMRX_BUSY,
3418c2ecf20Sopenharmony_ci						 SHIM_IMRX_BUSY);
3428c2ecf20Sopenharmony_ci
3438c2ecf20Sopenharmony_ci		/* Handle messages from DSP Core */
3448c2ecf20Sopenharmony_ci		if ((ipcd & SOF_IPC_PANIC_MAGIC_MASK) == SOF_IPC_PANIC_MAGIC) {
3458c2ecf20Sopenharmony_ci			snd_sof_dsp_panic(sdev, BDW_PANIC_OFFSET(ipcx) +
3468c2ecf20Sopenharmony_ci					  MBOX_OFFSET);
3478c2ecf20Sopenharmony_ci		} else {
3488c2ecf20Sopenharmony_ci			snd_sof_ipc_msgs_rx(sdev);
3498c2ecf20Sopenharmony_ci		}
3508c2ecf20Sopenharmony_ci
3518c2ecf20Sopenharmony_ci		bdw_host_done(sdev);
3528c2ecf20Sopenharmony_ci	}
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
3558c2ecf20Sopenharmony_ci}
3568c2ecf20Sopenharmony_ci
3578c2ecf20Sopenharmony_ci/*
3588c2ecf20Sopenharmony_ci * IPC Mailbox IO
3598c2ecf20Sopenharmony_ci */
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_cistatic int bdw_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg)
3628c2ecf20Sopenharmony_ci{
3638c2ecf20Sopenharmony_ci	/* send the message */
3648c2ecf20Sopenharmony_ci	sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data,
3658c2ecf20Sopenharmony_ci			  msg->msg_size);
3668c2ecf20Sopenharmony_ci	snd_sof_dsp_write(sdev, BDW_DSP_BAR, SHIM_IPCX, SHIM_IPCX_BUSY);
3678c2ecf20Sopenharmony_ci
3688c2ecf20Sopenharmony_ci	return 0;
3698c2ecf20Sopenharmony_ci}
3708c2ecf20Sopenharmony_ci
3718c2ecf20Sopenharmony_cistatic void bdw_get_reply(struct snd_sof_dev *sdev)
3728c2ecf20Sopenharmony_ci{
3738c2ecf20Sopenharmony_ci	struct snd_sof_ipc_msg *msg = sdev->msg;
3748c2ecf20Sopenharmony_ci	struct sof_ipc_reply reply;
3758c2ecf20Sopenharmony_ci	int ret = 0;
3768c2ecf20Sopenharmony_ci
3778c2ecf20Sopenharmony_ci	/*
3788c2ecf20Sopenharmony_ci	 * Sometimes, there is unexpected reply ipc arriving. The reply
3798c2ecf20Sopenharmony_ci	 * ipc belongs to none of the ipcs sent from driver.
3808c2ecf20Sopenharmony_ci	 * In this case, the driver must ignore the ipc.
3818c2ecf20Sopenharmony_ci	 */
3828c2ecf20Sopenharmony_ci	if (!msg) {
3838c2ecf20Sopenharmony_ci		dev_warn(sdev->dev, "unexpected ipc interrupt raised!\n");
3848c2ecf20Sopenharmony_ci		return;
3858c2ecf20Sopenharmony_ci	}
3868c2ecf20Sopenharmony_ci
3878c2ecf20Sopenharmony_ci	/* get reply */
3888c2ecf20Sopenharmony_ci	sof_mailbox_read(sdev, sdev->host_box.offset, &reply, sizeof(reply));
3898c2ecf20Sopenharmony_ci
3908c2ecf20Sopenharmony_ci	if (reply.error < 0) {
3918c2ecf20Sopenharmony_ci		memcpy(msg->reply_data, &reply, sizeof(reply));
3928c2ecf20Sopenharmony_ci		ret = reply.error;
3938c2ecf20Sopenharmony_ci	} else {
3948c2ecf20Sopenharmony_ci		/* reply correct size ? */
3958c2ecf20Sopenharmony_ci		if (reply.hdr.size != msg->reply_size) {
3968c2ecf20Sopenharmony_ci			dev_err(sdev->dev, "error: reply expected %zu got %u bytes\n",
3978c2ecf20Sopenharmony_ci				msg->reply_size, reply.hdr.size);
3988c2ecf20Sopenharmony_ci			ret = -EINVAL;
3998c2ecf20Sopenharmony_ci		}
4008c2ecf20Sopenharmony_ci
4018c2ecf20Sopenharmony_ci		/* read the message */
4028c2ecf20Sopenharmony_ci		if (msg->reply_size > 0)
4038c2ecf20Sopenharmony_ci			sof_mailbox_read(sdev, sdev->host_box.offset,
4048c2ecf20Sopenharmony_ci					 msg->reply_data, msg->reply_size);
4058c2ecf20Sopenharmony_ci	}
4068c2ecf20Sopenharmony_ci
4078c2ecf20Sopenharmony_ci	msg->reply_error = ret;
4088c2ecf20Sopenharmony_ci}
4098c2ecf20Sopenharmony_ci
4108c2ecf20Sopenharmony_cistatic int bdw_get_mailbox_offset(struct snd_sof_dev *sdev)
4118c2ecf20Sopenharmony_ci{
4128c2ecf20Sopenharmony_ci	return MBOX_OFFSET;
4138c2ecf20Sopenharmony_ci}
4148c2ecf20Sopenharmony_ci
4158c2ecf20Sopenharmony_cistatic int bdw_get_window_offset(struct snd_sof_dev *sdev, u32 id)
4168c2ecf20Sopenharmony_ci{
4178c2ecf20Sopenharmony_ci	return MBOX_OFFSET;
4188c2ecf20Sopenharmony_ci}
4198c2ecf20Sopenharmony_ci
4208c2ecf20Sopenharmony_cistatic void bdw_host_done(struct snd_sof_dev *sdev)
4218c2ecf20Sopenharmony_ci{
4228c2ecf20Sopenharmony_ci	/* clear BUSY bit and set DONE bit - accept new messages */
4238c2ecf20Sopenharmony_ci	snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_IPCD,
4248c2ecf20Sopenharmony_ci					 SHIM_IPCD_BUSY | SHIM_IPCD_DONE,
4258c2ecf20Sopenharmony_ci					 SHIM_IPCD_DONE);
4268c2ecf20Sopenharmony_ci
4278c2ecf20Sopenharmony_ci	/* unmask busy interrupt */
4288c2ecf20Sopenharmony_ci	snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_IMRX,
4298c2ecf20Sopenharmony_ci					 SHIM_IMRX_BUSY, 0);
4308c2ecf20Sopenharmony_ci}
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_cistatic void bdw_dsp_done(struct snd_sof_dev *sdev)
4338c2ecf20Sopenharmony_ci{
4348c2ecf20Sopenharmony_ci	/* clear DONE bit - tell DSP we have completed */
4358c2ecf20Sopenharmony_ci	snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_IPCX,
4368c2ecf20Sopenharmony_ci					 SHIM_IPCX_DONE, 0);
4378c2ecf20Sopenharmony_ci
4388c2ecf20Sopenharmony_ci	/* unmask Done interrupt */
4398c2ecf20Sopenharmony_ci	snd_sof_dsp_update_bits_unlocked(sdev, BDW_DSP_BAR, SHIM_IMRX,
4408c2ecf20Sopenharmony_ci					 SHIM_IMRX_DONE, 0);
4418c2ecf20Sopenharmony_ci}
4428c2ecf20Sopenharmony_ci
4438c2ecf20Sopenharmony_ci/*
4448c2ecf20Sopenharmony_ci * Probe and remove.
4458c2ecf20Sopenharmony_ci */
4468c2ecf20Sopenharmony_cistatic int bdw_probe(struct snd_sof_dev *sdev)
4478c2ecf20Sopenharmony_ci{
4488c2ecf20Sopenharmony_ci	struct snd_sof_pdata *pdata = sdev->pdata;
4498c2ecf20Sopenharmony_ci	const struct sof_dev_desc *desc = pdata->desc;
4508c2ecf20Sopenharmony_ci	struct platform_device *pdev =
4518c2ecf20Sopenharmony_ci		container_of(sdev->dev, struct platform_device, dev);
4528c2ecf20Sopenharmony_ci	struct resource *mmio;
4538c2ecf20Sopenharmony_ci	u32 base, size;
4548c2ecf20Sopenharmony_ci	int ret;
4558c2ecf20Sopenharmony_ci
4568c2ecf20Sopenharmony_ci	/* LPE base */
4578c2ecf20Sopenharmony_ci	mmio = platform_get_resource(pdev, IORESOURCE_MEM,
4588c2ecf20Sopenharmony_ci				     desc->resindex_lpe_base);
4598c2ecf20Sopenharmony_ci	if (mmio) {
4608c2ecf20Sopenharmony_ci		base = mmio->start;
4618c2ecf20Sopenharmony_ci		size = resource_size(mmio);
4628c2ecf20Sopenharmony_ci	} else {
4638c2ecf20Sopenharmony_ci		dev_err(sdev->dev, "error: failed to get LPE base at idx %d\n",
4648c2ecf20Sopenharmony_ci			desc->resindex_lpe_base);
4658c2ecf20Sopenharmony_ci		return -EINVAL;
4668c2ecf20Sopenharmony_ci	}
4678c2ecf20Sopenharmony_ci
4688c2ecf20Sopenharmony_ci	dev_dbg(sdev->dev, "LPE PHY base at 0x%x size 0x%x", base, size);
4698c2ecf20Sopenharmony_ci	sdev->bar[BDW_DSP_BAR] = devm_ioremap(sdev->dev, base, size);
4708c2ecf20Sopenharmony_ci	if (!sdev->bar[BDW_DSP_BAR]) {
4718c2ecf20Sopenharmony_ci		dev_err(sdev->dev,
4728c2ecf20Sopenharmony_ci			"error: failed to ioremap LPE base 0x%x size 0x%x\n",
4738c2ecf20Sopenharmony_ci			base, size);
4748c2ecf20Sopenharmony_ci		return -ENODEV;
4758c2ecf20Sopenharmony_ci	}
4768c2ecf20Sopenharmony_ci	dev_dbg(sdev->dev, "LPE VADDR %p\n", sdev->bar[BDW_DSP_BAR]);
4778c2ecf20Sopenharmony_ci
4788c2ecf20Sopenharmony_ci	/* TODO: add offsets */
4798c2ecf20Sopenharmony_ci	sdev->mmio_bar = BDW_DSP_BAR;
4808c2ecf20Sopenharmony_ci	sdev->mailbox_bar = BDW_DSP_BAR;
4818c2ecf20Sopenharmony_ci	sdev->dsp_oops_offset = MBOX_OFFSET;
4828c2ecf20Sopenharmony_ci
4838c2ecf20Sopenharmony_ci	/* PCI base */
4848c2ecf20Sopenharmony_ci	mmio = platform_get_resource(pdev, IORESOURCE_MEM,
4858c2ecf20Sopenharmony_ci				     desc->resindex_pcicfg_base);
4868c2ecf20Sopenharmony_ci	if (mmio) {
4878c2ecf20Sopenharmony_ci		base = mmio->start;
4888c2ecf20Sopenharmony_ci		size = resource_size(mmio);
4898c2ecf20Sopenharmony_ci	} else {
4908c2ecf20Sopenharmony_ci		dev_err(sdev->dev, "error: failed to get PCI base at idx %d\n",
4918c2ecf20Sopenharmony_ci			desc->resindex_pcicfg_base);
4928c2ecf20Sopenharmony_ci		return -ENODEV;
4938c2ecf20Sopenharmony_ci	}
4948c2ecf20Sopenharmony_ci
4958c2ecf20Sopenharmony_ci	dev_dbg(sdev->dev, "PCI base at 0x%x size 0x%x", base, size);
4968c2ecf20Sopenharmony_ci	sdev->bar[BDW_PCI_BAR] = devm_ioremap(sdev->dev, base, size);
4978c2ecf20Sopenharmony_ci	if (!sdev->bar[BDW_PCI_BAR]) {
4988c2ecf20Sopenharmony_ci		dev_err(sdev->dev,
4998c2ecf20Sopenharmony_ci			"error: failed to ioremap PCI base 0x%x size 0x%x\n",
5008c2ecf20Sopenharmony_ci			base, size);
5018c2ecf20Sopenharmony_ci		return -ENODEV;
5028c2ecf20Sopenharmony_ci	}
5038c2ecf20Sopenharmony_ci	dev_dbg(sdev->dev, "PCI VADDR %p\n", sdev->bar[BDW_PCI_BAR]);
5048c2ecf20Sopenharmony_ci
5058c2ecf20Sopenharmony_ci	/* register our IRQ */
5068c2ecf20Sopenharmony_ci	sdev->ipc_irq = platform_get_irq(pdev, desc->irqindex_host_ipc);
5078c2ecf20Sopenharmony_ci	if (sdev->ipc_irq < 0)
5088c2ecf20Sopenharmony_ci		return sdev->ipc_irq;
5098c2ecf20Sopenharmony_ci
5108c2ecf20Sopenharmony_ci	dev_dbg(sdev->dev, "using IRQ %d\n", sdev->ipc_irq);
5118c2ecf20Sopenharmony_ci	ret = devm_request_threaded_irq(sdev->dev, sdev->ipc_irq,
5128c2ecf20Sopenharmony_ci					bdw_irq_handler, bdw_irq_thread,
5138c2ecf20Sopenharmony_ci					IRQF_SHARED, "AudioDSP", sdev);
5148c2ecf20Sopenharmony_ci	if (ret < 0) {
5158c2ecf20Sopenharmony_ci		dev_err(sdev->dev, "error: failed to register IRQ %d\n",
5168c2ecf20Sopenharmony_ci			sdev->ipc_irq);
5178c2ecf20Sopenharmony_ci		return ret;
5188c2ecf20Sopenharmony_ci	}
5198c2ecf20Sopenharmony_ci
5208c2ecf20Sopenharmony_ci	/* enable the DSP SHIM */
5218c2ecf20Sopenharmony_ci	ret = bdw_set_dsp_D0(sdev);
5228c2ecf20Sopenharmony_ci	if (ret < 0) {
5238c2ecf20Sopenharmony_ci		dev_err(sdev->dev, "error: failed to set DSP D0\n");
5248c2ecf20Sopenharmony_ci		return ret;
5258c2ecf20Sopenharmony_ci	}
5268c2ecf20Sopenharmony_ci
5278c2ecf20Sopenharmony_ci	/* DSP DMA can only access low 31 bits of host memory */
5288c2ecf20Sopenharmony_ci	ret = dma_coerce_mask_and_coherent(sdev->dev, DMA_BIT_MASK(31));
5298c2ecf20Sopenharmony_ci	if (ret < 0) {
5308c2ecf20Sopenharmony_ci		dev_err(sdev->dev, "error: failed to set DMA mask %d\n", ret);
5318c2ecf20Sopenharmony_ci		return ret;
5328c2ecf20Sopenharmony_ci	}
5338c2ecf20Sopenharmony_ci
5348c2ecf20Sopenharmony_ci	/* set default mailbox */
5358c2ecf20Sopenharmony_ci	snd_sof_dsp_mailbox_init(sdev, MBOX_OFFSET, MBOX_SIZE, 0, 0);
5368c2ecf20Sopenharmony_ci
5378c2ecf20Sopenharmony_ci	return ret;
5388c2ecf20Sopenharmony_ci}
5398c2ecf20Sopenharmony_ci
5408c2ecf20Sopenharmony_cistatic void bdw_machine_select(struct snd_sof_dev *sdev)
5418c2ecf20Sopenharmony_ci{
5428c2ecf20Sopenharmony_ci	struct snd_sof_pdata *sof_pdata = sdev->pdata;
5438c2ecf20Sopenharmony_ci	const struct sof_dev_desc *desc = sof_pdata->desc;
5448c2ecf20Sopenharmony_ci	struct snd_soc_acpi_mach *mach;
5458c2ecf20Sopenharmony_ci
5468c2ecf20Sopenharmony_ci	mach = snd_soc_acpi_find_machine(desc->machines);
5478c2ecf20Sopenharmony_ci	if (!mach) {
5488c2ecf20Sopenharmony_ci		dev_warn(sdev->dev, "warning: No matching ASoC machine driver found\n");
5498c2ecf20Sopenharmony_ci		return;
5508c2ecf20Sopenharmony_ci	}
5518c2ecf20Sopenharmony_ci
5528c2ecf20Sopenharmony_ci	sof_pdata->tplg_filename = mach->sof_tplg_filename;
5538c2ecf20Sopenharmony_ci	mach->mach_params.acpi_ipc_irq_index = desc->irqindex_host_ipc;
5548c2ecf20Sopenharmony_ci	sof_pdata->machine = mach;
5558c2ecf20Sopenharmony_ci}
5568c2ecf20Sopenharmony_ci
5578c2ecf20Sopenharmony_cistatic void bdw_set_mach_params(const struct snd_soc_acpi_mach *mach,
5588c2ecf20Sopenharmony_ci				struct device *dev)
5598c2ecf20Sopenharmony_ci{
5608c2ecf20Sopenharmony_ci	struct snd_soc_acpi_mach_params *mach_params;
5618c2ecf20Sopenharmony_ci
5628c2ecf20Sopenharmony_ci	mach_params = (struct snd_soc_acpi_mach_params *)&mach->mach_params;
5638c2ecf20Sopenharmony_ci	mach_params->platform = dev_name(dev);
5648c2ecf20Sopenharmony_ci}
5658c2ecf20Sopenharmony_ci
5668c2ecf20Sopenharmony_ci/* Broadwell DAIs */
5678c2ecf20Sopenharmony_cistatic struct snd_soc_dai_driver bdw_dai[] = {
5688c2ecf20Sopenharmony_ci{
5698c2ecf20Sopenharmony_ci	.name = "ssp0-port",
5708c2ecf20Sopenharmony_ci	.playback = {
5718c2ecf20Sopenharmony_ci		.channels_min = 1,
5728c2ecf20Sopenharmony_ci		.channels_max = 8,
5738c2ecf20Sopenharmony_ci	},
5748c2ecf20Sopenharmony_ci	.capture = {
5758c2ecf20Sopenharmony_ci		.channels_min = 1,
5768c2ecf20Sopenharmony_ci		.channels_max = 8,
5778c2ecf20Sopenharmony_ci	},
5788c2ecf20Sopenharmony_ci},
5798c2ecf20Sopenharmony_ci{
5808c2ecf20Sopenharmony_ci	.name = "ssp1-port",
5818c2ecf20Sopenharmony_ci	.playback = {
5828c2ecf20Sopenharmony_ci		.channels_min = 1,
5838c2ecf20Sopenharmony_ci		.channels_max = 8,
5848c2ecf20Sopenharmony_ci	},
5858c2ecf20Sopenharmony_ci	.capture = {
5868c2ecf20Sopenharmony_ci		.channels_min = 1,
5878c2ecf20Sopenharmony_ci		.channels_max = 8,
5888c2ecf20Sopenharmony_ci	},
5898c2ecf20Sopenharmony_ci},
5908c2ecf20Sopenharmony_ci};
5918c2ecf20Sopenharmony_ci
5928c2ecf20Sopenharmony_ci/* broadwell ops */
5938c2ecf20Sopenharmony_ciconst struct snd_sof_dsp_ops sof_bdw_ops = {
5948c2ecf20Sopenharmony_ci	/*Device init */
5958c2ecf20Sopenharmony_ci	.probe          = bdw_probe,
5968c2ecf20Sopenharmony_ci
5978c2ecf20Sopenharmony_ci	/* DSP Core Control */
5988c2ecf20Sopenharmony_ci	.run            = bdw_run,
5998c2ecf20Sopenharmony_ci	.reset          = bdw_reset,
6008c2ecf20Sopenharmony_ci
6018c2ecf20Sopenharmony_ci	/* Register IO */
6028c2ecf20Sopenharmony_ci	.write		= sof_io_write,
6038c2ecf20Sopenharmony_ci	.read		= sof_io_read,
6048c2ecf20Sopenharmony_ci	.write64	= sof_io_write64,
6058c2ecf20Sopenharmony_ci	.read64		= sof_io_read64,
6068c2ecf20Sopenharmony_ci
6078c2ecf20Sopenharmony_ci	/* Block IO */
6088c2ecf20Sopenharmony_ci	.block_read	= sof_block_read,
6098c2ecf20Sopenharmony_ci	.block_write	= sof_block_write,
6108c2ecf20Sopenharmony_ci
6118c2ecf20Sopenharmony_ci	/* ipc */
6128c2ecf20Sopenharmony_ci	.send_msg	= bdw_send_msg,
6138c2ecf20Sopenharmony_ci	.fw_ready	= sof_fw_ready,
6148c2ecf20Sopenharmony_ci	.get_mailbox_offset = bdw_get_mailbox_offset,
6158c2ecf20Sopenharmony_ci	.get_window_offset = bdw_get_window_offset,
6168c2ecf20Sopenharmony_ci
6178c2ecf20Sopenharmony_ci	.ipc_msg_data	= intel_ipc_msg_data,
6188c2ecf20Sopenharmony_ci	.ipc_pcm_params	= intel_ipc_pcm_params,
6198c2ecf20Sopenharmony_ci
6208c2ecf20Sopenharmony_ci	/* machine driver */
6218c2ecf20Sopenharmony_ci	.machine_select = bdw_machine_select,
6228c2ecf20Sopenharmony_ci	.machine_register = sof_machine_register,
6238c2ecf20Sopenharmony_ci	.machine_unregister = sof_machine_unregister,
6248c2ecf20Sopenharmony_ci	.set_mach_params = bdw_set_mach_params,
6258c2ecf20Sopenharmony_ci
6268c2ecf20Sopenharmony_ci	/* debug */
6278c2ecf20Sopenharmony_ci	.debug_map  = bdw_debugfs,
6288c2ecf20Sopenharmony_ci	.debug_map_count    = ARRAY_SIZE(bdw_debugfs),
6298c2ecf20Sopenharmony_ci	.dbg_dump   = bdw_dump,
6308c2ecf20Sopenharmony_ci
6318c2ecf20Sopenharmony_ci	/* stream callbacks */
6328c2ecf20Sopenharmony_ci	.pcm_open	= intel_pcm_open,
6338c2ecf20Sopenharmony_ci	.pcm_close	= intel_pcm_close,
6348c2ecf20Sopenharmony_ci
6358c2ecf20Sopenharmony_ci	/* Module loading */
6368c2ecf20Sopenharmony_ci	.load_module    = snd_sof_parse_module_memcpy,
6378c2ecf20Sopenharmony_ci
6388c2ecf20Sopenharmony_ci	/*Firmware loading */
6398c2ecf20Sopenharmony_ci	.load_firmware	= snd_sof_load_firmware_memcpy,
6408c2ecf20Sopenharmony_ci
6418c2ecf20Sopenharmony_ci	/* DAI drivers */
6428c2ecf20Sopenharmony_ci	.drv = bdw_dai,
6438c2ecf20Sopenharmony_ci	.num_drv = ARRAY_SIZE(bdw_dai),
6448c2ecf20Sopenharmony_ci
6458c2ecf20Sopenharmony_ci	/* ALSA HW info flags */
6468c2ecf20Sopenharmony_ci	.hw_info =	SNDRV_PCM_INFO_MMAP |
6478c2ecf20Sopenharmony_ci			SNDRV_PCM_INFO_MMAP_VALID |
6488c2ecf20Sopenharmony_ci			SNDRV_PCM_INFO_INTERLEAVED |
6498c2ecf20Sopenharmony_ci			SNDRV_PCM_INFO_PAUSE |
6508c2ecf20Sopenharmony_ci			SNDRV_PCM_INFO_BATCH,
6518c2ecf20Sopenharmony_ci
6528c2ecf20Sopenharmony_ci	.arch_ops = &sof_xtensa_arch_ops,
6538c2ecf20Sopenharmony_ci};
6548c2ecf20Sopenharmony_ciEXPORT_SYMBOL_NS(sof_bdw_ops, SND_SOC_SOF_BROADWELL);
6558c2ecf20Sopenharmony_ci
6568c2ecf20Sopenharmony_ciconst struct sof_intel_dsp_desc bdw_chip_info = {
6578c2ecf20Sopenharmony_ci	.cores_num = 1,
6588c2ecf20Sopenharmony_ci	.host_managed_cores_mask = 1,
6598c2ecf20Sopenharmony_ci};
6608c2ecf20Sopenharmony_ciEXPORT_SYMBOL_NS(bdw_chip_info, SND_SOC_SOF_BROADWELL);
6618c2ecf20Sopenharmony_ci
6628c2ecf20Sopenharmony_ciMODULE_LICENSE("Dual BSD/GPL");
6638c2ecf20Sopenharmony_ciMODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HIFI_EP_IPC);
6648c2ecf20Sopenharmony_ciMODULE_IMPORT_NS(SND_SOC_SOF_XTENSA);
665