diff mbox series

[01/21] ASoC: SOF: Intel: Add BYT, CHT and BSW DSP HW support.

Message ID 20181211213029.28801-2-pierre-louis.bossart@linux.intel.com (mailing list archive)
State New, archived
Headers show
Series Sound Open Firmware (SOF) - Intel support | expand

Commit Message

Pierre-Louis Bossart Dec. 11, 2018, 9:30 p.m. UTC
From: Liam Girdwood <liam.r.girdwood@linux.intel.com>

Add support for the audio DSP hardware found on Intel Baytrail,
Cherrytrail and Braswell based devices.

Signed-off-by: Rander Wang <rander.wang@linux.intel.com>
Signed-off-by: Pan Xiuli <xiuli.pan@linux.intel.com>
Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
---
 sound/soc/sof/intel/byt.c  | 805 +++++++++++++++++++++++++++++++++++++
 sound/soc/sof/intel/shim.h | 159 ++++++++
 2 files changed, 964 insertions(+)
 create mode 100644 sound/soc/sof/intel/byt.c
 create mode 100644 sound/soc/sof/intel/shim.h

Comments

Takashi Sakamoto Dec. 12, 2018, 4:08 a.m. UTC | #1
Hi,

I have small nitpicking.

On 2018/12/12 6:30, Pierre-Louis Bossart wrote:
> From: Liam Girdwood <liam.r.girdwood@linux.intel.com>
> 
> Add support for the audio DSP hardware found on Intel Baytrail,
> Cherrytrail and Braswell based devices.
> 
> Signed-off-by: Rander Wang <rander.wang@linux.intel.com>
> Signed-off-by: Pan Xiuli <xiuli.pan@linux.intel.com>
> Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
> Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
> ---
>   sound/soc/sof/intel/byt.c  | 805 +++++++++++++++++++++++++++++++++++++
>   sound/soc/sof/intel/shim.h | 159 ++++++++
>   2 files changed, 964 insertions(+)
>   create mode 100644 sound/soc/sof/intel/byt.c
>   create mode 100644 sound/soc/sof/intel/shim.h
> ..
> diff --git a/sound/soc/sof/intel/shim.h b/sound/soc/sof/intel/shim.h
> new file mode 100644
> index 000000000000..2fdcb2d262f4
> --- /dev/null
> +++ b/sound/soc/sof/intel/shim.h
> @@ -0,0 +1,159 @@
> ...
> +extern struct snd_sof_dsp_ops sof_byt_ops;
> +extern struct snd_sof_dsp_ops sof_cht_ops;

These two symbols are found in this patch.

> +extern struct snd_sof_dsp_ops sof_hsw_ops;

This symbol is added in second patch and this first patch has
no reference to it.

> +extern struct snd_sof_dsp_ops sof_bdw_ops;

This symbol is added in third patch and this first patch has
no reference to it.

> +
> +#endif

I think it better to add these extern declarations when adding
corresponding symbols (Of course no issues as is).

Furthermore, if you have no plan to change contents of these symbols in
kernel run time, it's better to have 'const' qualifier to locate the
symbol to readonly section. However, user of these symbols is machine
driver and you have a plan to implement it later. They can get 'const'
when you work for arrangement of existent/new codes.

In this meaning, it might be good to add a new member to 'struct
snd_soc_acpi_mach' for new drivers to refer to the const ops, then
'pdata' member is used from the existent drivers.


Regards

Takashi Sakamoto
Pierre-Louis Bossart Dec. 12, 2018, 2:45 p.m. UTC | #2
Thanks for the review.

>> +++ b/sound/soc/sof/intel/shim.h
>> @@ -0,0 +1,159 @@
>> ...
>> +extern struct snd_sof_dsp_ops sof_byt_ops;
>> +extern struct snd_sof_dsp_ops sof_cht_ops;
>
> These two symbols are found in this patch.
>
>> +extern struct snd_sof_dsp_ops sof_hsw_ops;
>
> This symbol is added in second patch and this first patch has
> no reference to it.
>
>> +extern struct snd_sof_dsp_ops sof_bdw_ops;
>
> This symbol is added in third patch and this first patch has
> no reference to it.
>
>> +
>> +#endif
>
> I think it better to add these extern declarations when adding
> corresponding symbols (Of course no issues as is).
Yes, that's no big deal. It won't break as is though since the build is 
added in the last patch.
>
> Furthermore, if you have no plan to change contents of these symbols in
> kernel run time, it's better to have 'const' qualifier to locate the
> symbol to readonly section. However, user of these symbols is machine
> driver and you have a plan to implement it later. They can get 'const'
> when you work for arrangement of existent/new codes.
Good point, I don't think the ops are changed, ever. I'll double-check 
and change if indeed this is the case, thanks for the suggestion.
>
> In this meaning, it might be good to add a new member to 'struct
> snd_soc_acpi_mach' for new drivers to refer to the const ops, then
> 'pdata' member is used from the existent drivers.
Sorry, I don't get your point. the ops structure is included in the 
sof_ops_table, not the snd_soc_acpi_mach.
Pierre-Louis Bossart Dec. 12, 2018, 7:24 p.m. UTC | #3
>>
>> Furthermore, if you have no plan to change contents of these symbols in
>> kernel run time, it's better to have 'const' qualifier to locate the
>> symbol to readonly section. However, user of these symbols is machine
>> driver and you have a plan to implement it later. They can get 'const'
>> when you work for arrangement of existent/new codes.
> Good point, I don't think the ops are changed, ever. I'll double-check 
> and change if indeed this is the case, thanks for the suggestion.
>>
>> In this meaning, it might be good to add a new member to 'struct
>> snd_soc_acpi_mach' for new drivers to refer to the const ops, then
>> 'pdata' member is used from the existent drivers.
> Sorry, I don't get your point. the ops structure is included in the 
> sof_ops_table, not the snd_soc_acpi_mach.

I get your point now, after moving all the ops to a const qualifier, I 
still have the 3 errors below. We should indeed have an ops field in the 
generic acpi structure, excellent suggestion. This change also helped 
identify that we have redundant/hidden declarations in hda.c, so we can 
improve the code further.

I'll do that at a later point though since it will impact 2 other 
drivers, for now I'll mark these as TODO with an explicit cast.

Thanks again for your feedback

-Pierre

sound/soc/sof/sof-acpi-dev.c: In function ‘sof_acpi_probe’:
sound/soc/sof/sof-acpi-dev.c:200:14: warning: assignment discards 
‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers]
   mach->pdata = ops;
               ^
   CC [M]  sound/soc/sof/sof-pci-dev.o
sound/soc/sof/sof-pci-dev.c: In function ‘sof_pci_probe’:
sound/soc/sof/sof-pci-dev.c:247:14: warning: assignment discards ‘const’ 
qualifier from pointer target type [-Wdiscarded-qualifiers]
   mach->pdata = ops;
               ^
   CC [M]  sound/soc/sof/sof-spi-dev.o
sound/soc/sof/sof-spi-dev.c: In function ‘sof_spi_probe’:
sound/soc/sof/sof-spi-dev.c:119:14: warning: assignment discards ‘const’ 
qualifier from pointer target type [-Wdiscarded-qualifiers]
   mach->pdata = sof_get_ops(desc, spi_mach_ops, ARRAY_SIZE(spi_mach_ops));
Yang, Libin Dec. 17, 2018, 1:40 p.m. UTC | #4
Hi Sakamoto,

>
>-------- Forwarded Message --------
>Subject: Re: [alsa-devel] [PATCH 01/21] ASoC: SOF: Intel: Add BYT, CHT and
>BSW DSP HW support.
>Date: Wed, 12 Dec 2018 13:08:48 +0900
>From: Takashi Sakamoto <o-takashi@sakamocchi.jp>
>To: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>,
>alsa-devel@alsa-project.org
>CC: Daniel Baluta <daniel.baluta@gmail.com>, andriy.shevchenko@intel.com,
>tiwai@suse.de, Pan Xiuli <xiuli.pan@linux.intel.com>,
>liam.r.girdwood@linux.intel.com, vkoul@kernel.org, broonie@kernel.org,
>sound-open-firmware@alsa-project.org, Rander Wang
><rander.wang@linux.intel.com>, Alan Cox <alan@linux.intel.com>
>
>Hi,
>
>I have small nitpicking.
>
>On 2018/12/12 6:30, Pierre-Louis Bossart wrote:
>> From: Liam Girdwood <liam.r.girdwood@linux.intel.com>
>>
>> Add support for the audio DSP hardware found on Intel Baytrail,
>> Cherrytrail and Braswell based devices.
>>
>> Signed-off-by: Rander Wang <rander.wang@linux.intel.com>
>> Signed-off-by: Pan Xiuli <xiuli.pan@linux.intel.com>
>> Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
>> Signed-off-by: Pierre-Louis Bossart
>> <pierre-louis.bossart@linux.intel.com>
>> ---
>>   sound/soc/sof/intel/byt.c  | 805
>+++++++++++++++++++++++++++++++++++++
>>   sound/soc/sof/intel/shim.h | 159 ++++++++
>>   2 files changed, 964 insertions(+)
>>   create mode 100644 sound/soc/sof/intel/byt.c
>>   create mode 100644 sound/soc/sof/intel/shim.h ..
>> diff --git a/sound/soc/sof/intel/shim.h b/sound/soc/sof/intel/shim.h
>> new file mode 100644 index 000000000000..2fdcb2d262f4
>> --- /dev/null
>> +++ b/sound/soc/sof/intel/shim.h
>> @@ -0,0 +1,159 @@
>> ...
>> +extern struct snd_sof_dsp_ops sof_byt_ops; extern struct
>> +snd_sof_dsp_ops sof_cht_ops;
>
>These two symbols are found in this patch.
>
>> +extern struct snd_sof_dsp_ops sof_hsw_ops;
>
>This symbol is added in second patch and this first patch has no reference to it.
>
>> +extern struct snd_sof_dsp_ops sof_bdw_ops;
>
>This symbol is added in third patch and this first patch has no reference to it.
>
>> +
>> +#endif
>
>I think it better to add these extern declarations when adding corresponding
>symbols (Of course no issues as is).
>
>Furthermore, if you have no plan to change contents of these symbols in
>kernel run time, it's better to have 'const' qualifier to locate the symbol to
>readonly section. However, user of these symbols is machine driver and you
>have a plan to implement it later. They can get 'const'
>when you work for arrangement of existent/new codes.
>
>In this meaning, it might be good to add a new member to 'struct
>snd_soc_acpi_mach' for new drivers to refer to the const ops, then 'pdata'
>member is used from the existent drivers.

I made a patch based on your suggestion. Could you please help review
to see if my understanding is right?
https://github.com/thesofproject/linux/pull/457

Regards,
Libin

>
>
>Regards
>
>Takashi Sakamoto
>_______________________________________________
>Alsa-devel mailing list
>Alsa-devel@alsa-project.org
>http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
Daniel Baluta Jan. 18, 2019, 8:14 a.m. UTC | #5
Hi Pierre,

<snip>

> +/* cherrytrail and braswell ops */
> +struct snd_sof_dsp_ops sof_cht_ops = {
> +       /* device init */
> +       .probe          = byt_probe,
> +
> +       /* DSP core boot / reset */
> +       .run            = byt_run,
> +       .reset          = byt_reset,
> +
> +       /* Register IO */
> +       .write          = sof_io_write,
> +       .read           = sof_io_read,
> +       .write64        = sof_io_write64,
> +       .read64         = sof_io_read64,
> +
> +       /* Block IO */
> +       .block_read     = sof_block_read,
> +       .block_write    = sof_block_write,
> +
> +       /* doorbell */
> +       .irq_handler    = byt_irq_handler,
> +       .irq_thread     = byt_irq_thread,
> +

What is the reason for having irq_handler/irq_thread functions inside the
snd_sof_dsp_ops structure?

These functions are never used outside via sdev->ops pointer.

thanks,
Daniel.
Pierre-Louis Bossart Jan. 18, 2019, 3:02 p.m. UTC | #6
>> +struct snd_sof_dsp_ops sof_cht_ops = {
>> +       /* device init */
>> +       .probe          = byt_probe,
>> +
>> +       /* DSP core boot / reset */
>> +       .run            = byt_run,
>> +       .reset          = byt_reset,
>> +
>> +       /* Register IO */
>> +       .write          = sof_io_write,
>> +       .read           = sof_io_read,
>> +       .write64        = sof_io_write64,
>> +       .read64         = sof_io_read64,
>> +
>> +       /* Block IO */
>> +       .block_read     = sof_block_read,
>> +       .block_write    = sof_block_write,
>> +
>> +       /* doorbell */
>> +       .irq_handler    = byt_irq_handler,
>> +       .irq_thread     = byt_irq_thread,
>> +
> What is the reason for having irq_handler/irq_thread functions inside the
> snd_sof_dsp_ops structure?
>
> These functions are never used outside via sdev->ops pointer.

Good point indeed, thanks for raising it. We were in the middle of 
tagging which ops are required/optional (feedback from Mark) but we 
started from the core and should have looked at the structure definition.

Most drivers are "self-contained" and can reference the irq_thread and 
irq_handler directly.

The exception where the abstraction is used is internal to the HDaudio 
stuff:

intel/hda.c:    ret = request_threaded_irq(sdev->ipc_irq, 
hda_dsp_ipc_irq_handler,
intel/hda.c: sof_ops(sdev)->irq_thread, IRQF_SHARED,

That's useful since there a minor variations between hardware 
generations and you want to hide the hardware-specific parts.

But as you point out, it's a "private" use of ops callbacks, the core 
doesn't touch this.

I have no explanation other than legacy/historical reasons or a shortcut 
to make one's life easier during development.  Liam and Keyon might know?

We could try and move this to a more "private" structure, the 
"chip_info" part might be more suitable for this?
Daniel Baluta Jan. 18, 2019, 3:29 p.m. UTC | #7
On Fri, Jan 18, 2019 at 5:03 PM Pierre-Louis Bossart
<pierre-louis.bossart@linux.intel.com> wrote:
>
>
> >> +struct snd_sof_dsp_ops sof_cht_ops = {
> >> +       /* device init */
> >> +       .probe          = byt_probe,
> >> +
> >> +       /* DSP core boot / reset */
> >> +       .run            = byt_run,
> >> +       .reset          = byt_reset,
> >> +
> >> +       /* Register IO */
> >> +       .write          = sof_io_write,
> >> +       .read           = sof_io_read,
> >> +       .write64        = sof_io_write64,
> >> +       .read64         = sof_io_read64,
> >> +
> >> +       /* Block IO */
> >> +       .block_read     = sof_block_read,
> >> +       .block_write    = sof_block_write,
> >> +
> >> +       /* doorbell */
> >> +       .irq_handler    = byt_irq_handler,
> >> +       .irq_thread     = byt_irq_thread,
> >> +
> > What is the reason for having irq_handler/irq_thread functions inside the
> > snd_sof_dsp_ops structure?
> >
> > These functions are never used outside via sdev->ops pointer.
>
> Good point indeed, thanks for raising it. We were in the middle of
> tagging which ops are required/optional (feedback from Mark) but we
> started from the core and should have looked at the structure definition.
>
> Most drivers are "self-contained" and can reference the irq_thread and
> irq_handler directly.
>
> The exception where the abstraction is used is internal to the HDaudio
> stuff:
>
> intel/hda.c:    ret = request_threaded_irq(sdev->ipc_irq,
> hda_dsp_ipc_irq_handler,
> intel/hda.c: sof_ops(sdev)->irq_thread, IRQF_SHARED,
>
> That's useful since there a minor variations between hardware
> generations and you want to hide the hardware-specific parts.
>
> But as you point out, it's a "private" use of ops callbacks, the core
> doesn't touch this.
>
> I have no explanation other than legacy/historical reasons or a shortcut
> to make one's life easier during development.  Liam and Keyon might know?
>
> We could try and move this to a more "private" structure, the
> "chip_info" part might be more suitable for this?

I have no preference over this, I was just confused and wanting to
know if one will use
these members in the future.

We can either move them to a more private structure or at least have a
comment saying that
these will not be used by the core.

I have few things to bring into discussion now, perhaps you can comment  on it.

Firstly, we might want to look at the mailbox controller
(drivers/mailbox/mailbox.c).
It looks like the communication from AP (application processor) and
the DSP uses shim + mailbox
in Intel implementation, which could be abstracted by a mailbox client.

The confusing part here is the naming. In the Linux kernel the shim
layer you use is abstracted
by the mailbox controller, while mailbox from Intel implementation is
really a shared memory area.

We have this already implemented for our mailbox (Messaging Unit) in
drivers/mailbox/imx-mailbox.c and
trying to integrate with SOF.

So, for IPC we have the following "naming" differences:
* imx mailbox MU - equivalent with SHIM layer from Intel SOF.
* imx shared memory - equivalent with mailbox layer from Intel SOF.

Secondly, the "doorbell" naming of the interrupts. It surely looks
like a doorbell because we notify the
DSP that we pushed some data in a shared memory area. Anyhow, besides
pushing data to the shared
memory area we also send some data with the notification too.

For example, in byt_send_msg we do:

sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data, msg->msg_size);
snd_sof_dsp_write64(sdev, BYT_DSP_BAR, SHIM_IPCX, cmd | SHIM_BYT_IPCX_BUSY);

Not sure how cmd is used on the DSP side. Anyhow, this is not really
important for the next version
of the patches. Just wanted to hear your opinion.

thanks,
Daniel.
Pierre-Louis Bossart Jan. 18, 2019, 4:14 p.m. UTC | #8
> I have few things to bring into discussion now, perhaps you can comment  on it.
>
> Firstly, we might want to look at the mailbox controller
> (drivers/mailbox/mailbox.c).
> It looks like the communication from AP (application processor) and
> the DSP uses shim + mailbox
> in Intel implementation, which could be abstracted by a mailbox client.
>
> The confusing part here is the naming. In the Linux kernel the shim
> layer you use is abstracted
> by the mailbox controller, while mailbox from Intel implementation is
> really a shared memory area.
>
> We have this already implemented for our mailbox (Messaging Unit) in
> drivers/mailbox/imx-mailbox.c and
> trying to integrate with SOF.
>
> So, for IPC we have the following "naming" differences:
> * imx mailbox MU - equivalent with SHIM layer from Intel SOF.
> * imx shared memory - equivalent with mailbox layer from Intel SOF.

the "shim" on the intel side is a mix of control capabilities. There are 
indeed IPC registers in there, but also clock, DMA and power control 
capabilities. I am not sure we can really remove direct access to the 
shim, it's really the host-visible set of DSP registers.

We'll look at the pointer to the i.mx mailbox, thanks for the information.

>
> Secondly, the "doorbell" naming of the interrupts. It surely looks
> like a doorbell because we notify the
> DSP that we pushed some data in a shared memory area. Anyhow, besides
> pushing data to the shared
> memory area we also send some data with the notification too.
>
> For example, in byt_send_msg we do:
>
> sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data, msg->msg_size);
> snd_sof_dsp_write64(sdev, BYT_DSP_BAR, SHIM_IPCX, cmd | SHIM_BYT_IPCX_BUSY);
>
> Not sure how cmd is used on the DSP side. Anyhow, this is not really
> important for the next version
> of the patches. Just wanted to hear your opinion.

Humm, that one looks like an exception as well, it makes no sense. This 
is over a year old. Liam, any memories of this?
Daniel Baluta Jan. 22, 2019, 7:35 a.m. UTC | #9
> +static int byt_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg)
> +{
> +       u64 cmd = msg->header;
> +
> +       /* send the message */
> +       sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data,
> +                         msg->msg_size);

I was wondering if the mailbox shared memory wouldn't be better
implemented as a queue.
Do you support playing multiple streams in parallel?

We have this use case where we need to to memory to memory
decoding/encoding with lots
of streams in parallel.
Pierre-Louis Bossart Jan. 22, 2019, 4:22 p.m. UTC | #10
On 1/22/19 1:35 AM, Daniel Baluta wrote:
>> +static int byt_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg)
>> +{
>> +       u64 cmd = msg->header;
>> +
>> +       /* send the message */
>> +       sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data,
>> +                         msg->msg_size);
> I was wondering if the mailbox shared memory wouldn't be better
> implemented as a queue.
> Do you support playing multiple streams in parallel?
>
> We have this use case where we need to to memory to memory
> decoding/encoding with lots
> of streams in parallel.

Sorry Daniel, I didn't get your point.

we do support multiple streams in parallel and there's been quite a few 
issues fixed in the IPC mechanisms due to concurrency. The IPC mechanism 
is serialized however since there are only few resources available, 
typically only a couple of doorbell registers and a small memory window. 
For multiple streams the PCM data is exchanged over DMA typically - the 
streams don't go over the IPC channel but the information related to a 
stream is passed using a tag or ID.

Can you clarify what you had in mind?
Daniel Baluta Jan. 22, 2019, 4:49 p.m. UTC | #11
On Tue, Jan 22, 2019 at 6:22 PM Pierre-Louis Bossart
<pierre-louis.bossart@linux.intel.com> wrote:
>
>
> On 1/22/19 1:35 AM, Daniel Baluta wrote:
> >> +static int byt_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg)
> >> +{
> >> +       u64 cmd = msg->header;
> >> +
> >> +       /* send the message */
> >> +       sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data,
> >> +                         msg->msg_size);
> > I was wondering if the mailbox shared memory wouldn't be better
> > implemented as a queue.
> > Do you support playing multiple streams in parallel?
> >
> > We have this use case where we need to to memory to memory
> > decoding/encoding with lots
> > of streams in parallel.
>
> Sorry Daniel, I didn't get your point.
>
> we do support multiple streams in parallel and there's been quite a few
> issues fixed in the IPC mechanisms due to concurrency. The IPC mechanism
> is serialized however since there are only few resources available,
> typically only a couple of doorbell registers and a small memory window.
> For multiple streams the PCM data is exchanged over DMA typically - the
> streams don't go over the IPC channel but the information related to a
> stream is passed using a tag or ID.
>

> Can you clarify what you had in mind?

Sometimes is hard feven for me to clarify that :)

The question was raised mostly because our audio framework
uses queues here instead just of a mailbox.

We might actually need to have an implementation ready to test
if this serialization has an impact on performance.

I will get back to you when this question will make more sense
in my mind.

thanks,
daniel.
diff mbox series

Patch

diff --git a/sound/soc/sof/intel/byt.c b/sound/soc/sof/intel/byt.c
new file mode 100644
index 000000000000..1695d67c3360
--- /dev/null
+++ b/sound/soc/sof/intel/byt.c
@@ -0,0 +1,805 @@ 
+// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
+//
+// This file is provided under a dual BSD/GPLv2 license.  When using or
+// redistributing this file, you may do so under either license.
+//
+// Copyright(c) 2018 Intel Corporation. All rights reserved.
+//
+// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
+//
+
+/*
+ * Hardware interface for audio DSP on Baytrail, Braswell and Cherrytrail.
+ */
+
+#include <linux/module.h>
+#include <sound/sof.h>
+#include <sound/sof/xtensa.h>
+#include "../ops.h"
+#include "shim.h"
+
+/* DSP memories */
+#define IRAM_OFFSET		0x0C0000
+#define IRAM_SIZE		(80 * 1024)
+#define DRAM_OFFSET		0x100000
+#define DRAM_SIZE		(160 * 1024)
+#define SHIM_OFFSET		0x140000
+#define SHIM_SIZE		0x100
+#define MBOX_OFFSET		0x144000
+#define MBOX_SIZE		0x1000
+#define EXCEPT_OFFSET		0x800
+
+/* DSP peripherals */
+#define DMAC0_OFFSET		0x098000
+#define DMAC1_OFFSET		0x09c000
+#define DMAC2_OFFSET		0x094000
+#define DMAC_SIZE		0x420
+#define SSP0_OFFSET		0x0a0000
+#define SSP1_OFFSET		0x0a1000
+#define SSP2_OFFSET		0x0a2000
+#define SSP3_OFFSET		0x0a4000
+#define SSP4_OFFSET		0x0a5000
+#define SSP5_OFFSET		0x0a6000
+#define SSP_SIZE		0x100
+
+#define BYT_STACK_DUMP_SIZE	32
+
+#define BYT_PCI_BAR_SIZE	0x200000
+
+#define BYT_PANIC_OFFSET(x)	(((x) & GENMASK_ULL(47, 32)) >> 32)
+
+/*
+ * Debug
+ */
+
+#define MBOX_DUMP_SIZE	0x30
+
+/* BARs */
+#define BYT_DSP_BAR		0
+#define BYT_PCI_BAR		1
+#define BYT_IMR_BAR		2
+
+static const struct snd_sof_debugfs_map byt_debugfs[] = {
+	{"dmac0", BYT_DSP_BAR, DMAC0_OFFSET, DMAC_SIZE},
+	{"dmac1", BYT_DSP_BAR,  DMAC1_OFFSET, DMAC_SIZE},
+	{"ssp0",  BYT_DSP_BAR, SSP0_OFFSET, SSP_SIZE},
+	{"ssp1", BYT_DSP_BAR, SSP1_OFFSET, SSP_SIZE},
+	{"ssp2", BYT_DSP_BAR, SSP2_OFFSET, SSP_SIZE},
+	{"iram", BYT_DSP_BAR, IRAM_OFFSET, IRAM_SIZE},
+	{"dram", BYT_DSP_BAR, DRAM_OFFSET, DRAM_SIZE},
+	{"shim", BYT_DSP_BAR, SHIM_OFFSET, SHIM_SIZE},
+};
+
+static const struct snd_sof_debugfs_map cht_debugfs[] = {
+	{"dmac0", BYT_DSP_BAR, DMAC0_OFFSET, DMAC_SIZE},
+	{"dmac1", BYT_DSP_BAR,  DMAC1_OFFSET, DMAC_SIZE},
+	{"dmac2", BYT_DSP_BAR,  DMAC2_OFFSET, DMAC_SIZE},
+	{"ssp0",  BYT_DSP_BAR, SSP0_OFFSET, SSP_SIZE},
+	{"ssp1", BYT_DSP_BAR, SSP1_OFFSET, SSP_SIZE},
+	{"ssp2", BYT_DSP_BAR, SSP2_OFFSET, SSP_SIZE},
+	{"ssp3", BYT_DSP_BAR, SSP3_OFFSET, SSP_SIZE},
+	{"ssp4", BYT_DSP_BAR, SSP4_OFFSET, SSP_SIZE},
+	{"ssp5", BYT_DSP_BAR, SSP5_OFFSET, SSP_SIZE},
+	{"iram", BYT_DSP_BAR, IRAM_OFFSET, IRAM_SIZE},
+	{"dram", BYT_DSP_BAR, DRAM_OFFSET, DRAM_SIZE},
+	{"shim", BYT_DSP_BAR, SHIM_OFFSET, SHIM_SIZE},
+};
+
+static int byt_cmd_done(struct snd_sof_dev *sdev, int dir);
+
+/*
+ * IPC Firmware ready.
+ */
+static void byt_get_windows(struct snd_sof_dev *sdev)
+{
+	struct sof_ipc_window_elem *elem;
+	u32 outbox_offset = 0;
+	u32 stream_offset = 0;
+	u32 inbox_offset = 0;
+	u32 outbox_size = 0;
+	u32 stream_size = 0;
+	u32 inbox_size = 0;
+	int i;
+
+	if (!sdev->info_window) {
+		dev_err(sdev->dev, "error: have no window info\n");
+		return;
+	}
+
+	for (i = 0; i < sdev->info_window->num_windows; i++) {
+		elem = &sdev->info_window->window[i];
+
+		switch (elem->type) {
+		case SOF_IPC_REGION_UPBOX:
+			inbox_offset = elem->offset + MBOX_OFFSET;
+			inbox_size = elem->size;
+			snd_sof_debugfs_io_create_item(sdev,
+						       sdev->bar[BYT_DSP_BAR] +
+						       inbox_offset,
+						       elem->size, "inbox");
+			break;
+		case SOF_IPC_REGION_DOWNBOX:
+			outbox_offset = elem->offset + MBOX_OFFSET;
+			outbox_size = elem->size;
+			snd_sof_debugfs_io_create_item(sdev,
+						       sdev->bar[BYT_DSP_BAR] +
+						       outbox_offset,
+						       elem->size, "outbox");
+			break;
+		case SOF_IPC_REGION_TRACE:
+			snd_sof_debugfs_io_create_item(sdev,
+						       sdev->bar[BYT_DSP_BAR] +
+						       elem->offset +
+						       MBOX_OFFSET,
+						       elem->size, "etrace");
+			break;
+		case SOF_IPC_REGION_DEBUG:
+			snd_sof_debugfs_io_create_item(sdev,
+						       sdev->bar[BYT_DSP_BAR] +
+						       elem->offset +
+						       MBOX_OFFSET,
+						       elem->size, "debug");
+			break;
+		case SOF_IPC_REGION_STREAM:
+			stream_offset = elem->offset + MBOX_OFFSET;
+			stream_size = elem->size;
+			snd_sof_debugfs_io_create_item(sdev,
+						       sdev->bar[BYT_DSP_BAR] +
+						       stream_offset,
+						       elem->size, "stream");
+			break;
+		case SOF_IPC_REGION_REGS:
+			snd_sof_debugfs_io_create_item(sdev,
+						       sdev->bar[BYT_DSP_BAR] +
+						       elem->offset +
+						       MBOX_OFFSET,
+						       elem->size, "regs");
+			break;
+		case SOF_IPC_REGION_EXCEPTION:
+			sdev->dsp_oops_offset = elem->offset + MBOX_OFFSET;
+			snd_sof_debugfs_io_create_item(sdev,
+						       sdev->bar[BYT_DSP_BAR] +
+						       elem->offset +
+						       MBOX_OFFSET,
+						       elem->size, "exception");
+			break;
+		default:
+			dev_err(sdev->dev, "error: get illegal window info\n");
+			return;
+		}
+	}
+
+	if (outbox_size == 0 || inbox_size == 0) {
+		dev_err(sdev->dev, "error: get illegal mailbox window\n");
+		return;
+	}
+
+	snd_sof_dsp_mailbox_init(sdev, inbox_offset, inbox_size,
+				 outbox_offset, outbox_size);
+	sdev->stream_box.offset = stream_offset;
+	sdev->stream_box.size = stream_size;
+
+	dev_dbg(sdev->dev, " mailbox upstream 0x%x - size 0x%x\n",
+		inbox_offset, inbox_size);
+	dev_dbg(sdev->dev, " mailbox downstream 0x%x - size 0x%x\n",
+		outbox_offset, outbox_size);
+	dev_dbg(sdev->dev, " stream region 0x%x - size 0x%x\n",
+		stream_offset, stream_size);
+}
+
+static int byt_fw_ready(struct snd_sof_dev *sdev, u32 msg_id)
+{
+	struct sof_ipc_fw_ready *fw_ready = &sdev->fw_ready;
+	u32 offset;
+	int ret;
+
+	/* mailbox must be on 4k boundary */
+	offset = MBOX_OFFSET;
+
+	dev_dbg(sdev->dev, "ipc: DSP is ready 0x%8.8x offset 0x%x\n",
+		msg_id, offset);
+
+	/* no need to re-check version/ABI for subsequent boots */
+	if (!sdev->first_boot)
+		return 0;
+
+	/* copy data from the DSP FW ready offset */
+	sof_block_read(sdev, offset, fw_ready, sizeof(*fw_ready));
+
+	snd_sof_dsp_mailbox_init(sdev, fw_ready->dspbox_offset,
+				 fw_ready->dspbox_size,
+				 fw_ready->hostbox_offset,
+				 fw_ready->hostbox_size);
+
+	/* make sure ABI version is compatible */
+	ret = snd_sof_ipc_valid(sdev);
+	if (ret < 0)
+		return ret;
+
+	/* now check for extended data */
+	snd_sof_fw_parse_ext_data(sdev, MBOX_OFFSET +
+				  sizeof(struct sof_ipc_fw_ready));
+
+	byt_get_windows(sdev);
+
+	return 0;
+}
+
+/*
+ * Debug
+ */
+
+static void byt_get_registers(struct snd_sof_dev *sdev,
+			      struct sof_ipc_dsp_oops_xtensa *xoops,
+			      struct sof_ipc_panic_info *panic_info,
+			      u32 *stack, size_t stack_words)
+{
+	/* first read regsisters */
+	sof_mailbox_read(sdev, sdev->dsp_oops_offset, xoops, sizeof(*xoops));
+
+	/* then get panic info */
+	sof_mailbox_read(sdev, sdev->dsp_oops_offset + sizeof(*xoops),
+			 panic_info, sizeof(*panic_info));
+
+	/* then get the stack */
+	sof_mailbox_read(sdev, sdev->dsp_oops_offset + sizeof(*xoops) +
+			   sizeof(*panic_info), stack,
+			   stack_words * sizeof(u32));
+}
+
+static void byt_dump(struct snd_sof_dev *sdev, u32 flags)
+{
+	struct sof_ipc_dsp_oops_xtensa xoops;
+	struct sof_ipc_panic_info panic_info;
+	u32 stack[BYT_STACK_DUMP_SIZE];
+	u32 status, panic;
+
+	/* now try generic SOF status messages */
+	status = snd_sof_dsp_read(sdev, BYT_DSP_BAR, SHIM_IPCD);
+	panic = snd_sof_dsp_read(sdev, BYT_DSP_BAR, SHIM_IPCX);
+	byt_get_registers(sdev, &xoops, &panic_info, stack,
+			  BYT_STACK_DUMP_SIZE);
+	snd_sof_get_status(sdev, status, panic, &xoops, &panic_info, stack,
+			   BYT_STACK_DUMP_SIZE);
+}
+
+/*
+ * IPC Doorbell IRQ handler and thread.
+ */
+
+static irqreturn_t byt_irq_handler(int irq, void *context)
+{
+	struct snd_sof_dev *sdev = (struct snd_sof_dev *)context;
+	u64 isr;
+	int ret = IRQ_NONE;
+
+	/* Interrupt arrived, check src */
+	isr = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_ISRX);
+	if (isr & (SHIM_ISRX_DONE | SHIM_ISRX_BUSY))
+		ret = IRQ_WAKE_THREAD;
+
+	return ret;
+}
+
+static irqreturn_t byt_irq_thread(int irq, void *context)
+{
+	struct snd_sof_dev *sdev = (struct snd_sof_dev *)context;
+	u64 ipcx, ipcd;
+	u64 imrx;
+
+	imrx = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_IMRX);
+	ipcx = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_IPCX);
+
+	/* reply message from DSP */
+	if (ipcx & SHIM_BYT_IPCX_DONE &&
+	    !(imrx & SHIM_IMRX_DONE)) {
+		/* Mask Done interrupt before first */
+		snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR,
+						   SHIM_IMRX,
+						   SHIM_IMRX_DONE,
+						   SHIM_IMRX_DONE);
+		/*
+		 * handle immediate reply from DSP core. If the msg is
+		 * found, set done bit in cmd_done which is called at the
+		 * end of message processing function, else set it here
+		 * because the done bit can't be set in cmd_done function
+		 * which is triggered by msg
+		 */
+		if (snd_sof_ipc_reply(sdev, ipcx))
+			byt_cmd_done(sdev, SOF_IPC_DSP_REPLY);
+	}
+
+	/* new message from DSP */
+	ipcd = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_IPCD);
+	if (ipcd & SHIM_BYT_IPCD_BUSY &&
+	    !(imrx & SHIM_IMRX_BUSY)) {
+		/* Mask Busy interrupt before return */
+		snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR,
+						   SHIM_IMRX,
+						   SHIM_IMRX_BUSY,
+						   SHIM_IMRX_BUSY);
+
+		/* Handle messages from DSP Core */
+		if ((ipcd & SOF_IPC_PANIC_MAGIC_MASK) == SOF_IPC_PANIC_MAGIC) {
+			snd_sof_dsp_panic(sdev, BYT_PANIC_OFFSET(ipcd) +
+					  MBOX_OFFSET);
+		} else {
+			snd_sof_ipc_msgs_rx(sdev);
+		}
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int byt_is_ready(struct snd_sof_dev *sdev)
+{
+	u64 ipcx;
+
+	ipcx = snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_IPCX);
+	if ((ipcx & SHIM_BYT_IPCX_BUSY) || (ipcx & SHIM_BYT_IPCX_DONE))
+		return 0;
+
+	return 1;
+}
+
+static int byt_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg)
+{
+	u64 cmd = msg->header;
+
+	/* send the message */
+	sof_mailbox_write(sdev, sdev->host_box.offset, msg->msg_data,
+			  msg->msg_size);
+	snd_sof_dsp_write64(sdev, BYT_DSP_BAR, SHIM_IPCX,
+			    cmd | SHIM_BYT_IPCX_BUSY);
+
+	return 0;
+}
+
+static int byt_get_reply(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg)
+{
+	struct sof_ipc_reply reply;
+	int ret = 0;
+	u32 size;
+
+	/* get reply */
+	sof_mailbox_read(sdev, sdev->host_box.offset, &reply, sizeof(reply));
+	if (reply.error < 0) {
+		size = sizeof(reply);
+		ret = reply.error;
+	} else {
+		/* reply correct size ? */
+		if (reply.hdr.size != msg->reply_size) {
+			dev_err(sdev->dev, "error: reply expected 0x%zx got 0x%x bytes\n",
+				msg->reply_size, reply.hdr.size);
+			size = msg->reply_size;
+			ret = -EINVAL;
+		} else {
+			size = reply.hdr.size;
+		}
+	}
+
+	/* read the message */
+	if (msg->msg_data && size > 0)
+		sof_mailbox_read(sdev, sdev->host_box.offset, msg->reply_data,
+				 size);
+
+	return ret;
+}
+
+static int byt_cmd_done(struct snd_sof_dev *sdev, int dir)
+{
+	if (dir == SOF_IPC_HOST_REPLY) {
+		/* clear BUSY bit and set DONE bit - accept new messages */
+		snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, SHIM_IPCD,
+						   SHIM_BYT_IPCD_BUSY |
+						   SHIM_BYT_IPCD_DONE,
+						   SHIM_BYT_IPCD_DONE);
+
+		/* unmask busy interrupt */
+		snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, SHIM_IMRX,
+						   SHIM_IMRX_BUSY, 0);
+	} else {
+		/* clear DONE bit - tell DSP we have completed */
+		snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, SHIM_IPCX,
+						   SHIM_BYT_IPCX_DONE, 0);
+
+		/* unmask Done interrupt */
+		snd_sof_dsp_update_bits64_unlocked(sdev, BYT_DSP_BAR, SHIM_IMRX,
+						   SHIM_IMRX_DONE, 0);
+	}
+
+	return 0;
+}
+
+/*
+ * DSP control.
+ */
+
+static int byt_run(struct snd_sof_dev *sdev)
+{
+	int tries = 10;
+
+	/* release stall and wait to unstall */
+	snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_CSR,
+				  SHIM_BYT_CSR_STALL, 0x0);
+	while (tries--) {
+		if (!(snd_sof_dsp_read64(sdev, BYT_DSP_BAR, SHIM_CSR) &
+		      SHIM_BYT_CSR_PWAITMODE))
+			break;
+		msleep(100);
+	}
+	if (tries < 0) {
+		dev_err(sdev->dev, "error:  unable to run DSP firmware\n");
+		byt_dump(sdev, SOF_DBG_REGS | SOF_DBG_MBOX);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static int byt_reset(struct snd_sof_dev *sdev)
+{
+	/* put DSP into reset, set reset vector and stall */
+	snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_CSR,
+				  SHIM_BYT_CSR_RST | SHIM_BYT_CSR_VECTOR_SEL |
+				  SHIM_BYT_CSR_STALL,
+				  SHIM_BYT_CSR_RST | SHIM_BYT_CSR_VECTOR_SEL |
+				  SHIM_BYT_CSR_STALL);
+
+	usleep_range(10, 15);
+
+	/* take DSP out of reset and keep stalled for FW loading */
+	snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_CSR,
+				  SHIM_BYT_CSR_RST, 0);
+
+	return 0;
+}
+
+/*
+ * Probe and remove.
+ */
+
+static int byt_acpi_probe(struct snd_sof_dev *sdev)
+{
+	struct snd_sof_pdata *pdata = sdev->pdata;
+	const struct sof_dev_desc *desc = pdata->desc;
+	struct platform_device *pdev =
+		container_of(sdev->parent, struct platform_device, dev);
+	struct resource *mmio;
+	u32 base, size;
+	int ret = 0;
+
+	/* set DSP arch ops */
+	sdev->arch_ops = &sof_xtensa_arch_ops;
+
+	/* DSP DMA can only access low 31 bits of host memory */
+	ret = dma_coerce_mask_and_coherent(sdev->dev, DMA_BIT_MASK(31));
+	if (ret < 0) {
+		dev_err(sdev->dev, "error: failed to set DMA mask %d\n", ret);
+		return ret;
+	}
+
+	/* LPE base */
+	mmio = platform_get_resource(pdev, IORESOURCE_MEM,
+				     desc->resindex_lpe_base);
+	if (mmio) {
+		base = mmio->start;
+		size = resource_size(mmio);
+	} else {
+		dev_err(sdev->dev, "error: failed to get LPE base at idx %d\n",
+			desc->resindex_lpe_base);
+		return -EINVAL;
+	}
+
+	dev_dbg(sdev->dev, "LPE PHY base at 0x%x size 0x%x", base, size);
+	sdev->bar[BYT_DSP_BAR] = devm_ioremap(sdev->dev, base, size);
+	if (!sdev->bar[BYT_DSP_BAR]) {
+		dev_err(sdev->dev, "error: failed to ioremap LPE base 0x%x size 0x%x\n",
+			base, size);
+		return -ENODEV;
+	}
+	dev_dbg(sdev->dev, "LPE VADDR %p\n", sdev->bar[BYT_DSP_BAR]);
+
+	/* TODO: add offsets */
+	sdev->mmio_bar = BYT_DSP_BAR;
+	sdev->mailbox_bar = BYT_DSP_BAR;
+
+	/* IMR base - optional */
+	if (desc->resindex_imr_base == -1)
+		goto irq;
+
+	mmio = platform_get_resource(pdev, IORESOURCE_MEM,
+				     desc->resindex_imr_base);
+	if (mmio) {
+		base = mmio->start;
+		size = resource_size(mmio);
+	} else {
+		dev_err(sdev->dev, "error: failed to get IMR base at idx %d\n",
+			desc->resindex_imr_base);
+		return -ENODEV;
+	}
+
+	/* some BIOSes don't map IMR */
+	if (base == 0x55aa55aa || base == 0x0) {
+		dev_info(sdev->dev, "IMR not set by BIOS. Ignoring\n");
+		goto irq;
+	}
+
+	dev_dbg(sdev->dev, "IMR base at 0x%x size 0x%x", base, size);
+	sdev->bar[BYT_IMR_BAR] = devm_ioremap(sdev->dev, base, size);
+	if (!sdev->bar[BYT_IMR_BAR]) {
+		dev_err(sdev->dev, "error: failed to ioremap IMR base 0x%x size 0x%x\n",
+			base, size);
+		return -ENODEV;
+	}
+	dev_dbg(sdev->dev, "IMR VADDR %p\n", sdev->bar[BYT_IMR_BAR]);
+
+irq:
+	/* register our IRQ */
+	sdev->ipc_irq = platform_get_irq(pdev, desc->irqindex_host_ipc);
+	if (sdev->ipc_irq < 0) {
+		dev_err(sdev->dev, "error: failed to get IRQ at index %d\n",
+			desc->irqindex_host_ipc);
+		return sdev->ipc_irq;
+	}
+
+	dev_dbg(sdev->dev, "using IRQ %d\n", sdev->ipc_irq);
+	ret = devm_request_threaded_irq(sdev->dev, sdev->ipc_irq,
+					byt_irq_handler, byt_irq_thread,
+					IRQF_SHARED, "AudioDSP", sdev);
+	if (ret < 0) {
+		dev_err(sdev->dev, "error: failed to register IRQ %d\n",
+			sdev->ipc_irq);
+		return ret;
+	}
+
+	/* enable Interrupt from both sides */
+	snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRX, 0x3, 0x0);
+	snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRD, 0x3, 0x0);
+
+	/* set BARS */
+	sdev->cl_bar = BYT_DSP_BAR;
+
+	/* set default mailbox offset for FW ready message */
+	sdev->dsp_box.offset = MBOX_OFFSET;
+
+	return ret;
+}
+
+static int byt_pci_probe(struct snd_sof_dev *sdev)
+{
+	struct snd_sof_pdata *pdata = sdev->pdata;
+	const struct sof_dev_desc *desc = pdata->desc;
+	struct pci_dev *pci = sdev->pci;
+	u32 base, size;
+	int ret = 0;
+
+	/* DSP DMA can only access low 31 bits of host memory */
+	ret = dma_coerce_mask_and_coherent(&pci->dev, DMA_BIT_MASK(31));
+	if (ret < 0) {
+		dev_err(sdev->dev, "error: failed to set DMA mask %d\n", ret);
+		return ret;
+	}
+
+	/* LPE base */
+	base = pci_resource_start(pci, desc->resindex_lpe_base) - IRAM_OFFSET;
+	size = BYT_PCI_BAR_SIZE;
+
+	dev_dbg(sdev->dev, "LPE PHY base at 0x%x size 0x%x", base, size);
+	sdev->bar[BYT_DSP_BAR] = devm_ioremap(sdev->dev, base, size);
+	if (!sdev->bar[BYT_DSP_BAR]) {
+		dev_err(sdev->dev, "error: failed to ioremap LPE base 0x%x size 0x%x\n",
+			base, size);
+		return -ENODEV;
+	}
+	dev_dbg(sdev->dev, "LPE VADDR %p\n", sdev->bar[BYT_DSP_BAR]);
+
+	/* IMR base - optional */
+	if (desc->resindex_imr_base == -1)
+		goto irq;
+
+	base = pci_resource_start(pci, desc->resindex_imr_base);
+	size = pci_resource_len(pci, desc->resindex_imr_base);
+
+	/* some BIOSes don't map IMR */
+	if (base == 0x55aa55aa || base == 0x0) {
+		dev_info(sdev->dev, "IMR not set by BIOS. Ignoring\n");
+		goto irq;
+	}
+
+	dev_dbg(sdev->dev, "IMR base at 0x%x size 0x%x", base, size);
+	sdev->bar[BYT_IMR_BAR] = devm_ioremap(sdev->dev, base, size);
+	if (!sdev->bar[BYT_IMR_BAR]) {
+		dev_err(sdev->dev, "error: failed to ioremap IMR base 0x%x size 0x%x\n",
+			base, size);
+		return -ENODEV;
+	}
+	dev_dbg(sdev->dev, "IMR VADDR %p\n", sdev->bar[BYT_IMR_BAR]);
+
+irq:
+	/* register our IRQ */
+	sdev->ipc_irq = pci->irq;
+	dev_dbg(sdev->dev, "using IRQ %d\n", sdev->ipc_irq);
+	ret = devm_request_threaded_irq(sdev->dev, sdev->ipc_irq,
+					byt_irq_handler, byt_irq_thread,
+					0, "AudioDSP", sdev);
+	if (ret < 0) {
+		dev_err(sdev->dev, "error: failed to register IRQ %d\n",
+			sdev->ipc_irq);
+		return ret;
+	}
+
+	/* enable Interrupt from both sides */
+	snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRX, 0x3, 0x0);
+	snd_sof_dsp_update_bits64(sdev, BYT_DSP_BAR, SHIM_IMRD, 0x3, 0x0);
+
+	/* set BARS */
+	sdev->cl_bar = BYT_DSP_BAR;
+
+	/* set default mailbox offset for FW ready message */
+	sdev->dsp_box.offset = MBOX_OFFSET;
+
+	return ret;
+}
+
+static int byt_probe(struct snd_sof_dev *sdev)
+{
+	if (sdev->pci)
+		return byt_pci_probe(sdev);
+
+	return byt_acpi_probe(sdev);
+}
+
+#define BYT_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | \
+	SNDRV_PCM_FMTBIT_S32_LE)
+
+/* Baytrail DAIs */
+static struct snd_soc_dai_driver byt_dai[] = {
+{
+	.name = "ssp0-port",
+	.playback = SOF_DAI_STREAM("ssp0 Tx", 1, 8,
+				   SNDRV_PCM_RATE_8000_192000, BYT_FORMATS),
+	.capture = SOF_DAI_STREAM("ssp0 Rx", 1, 8,
+				  SNDRV_PCM_RATE_8000_192000, BYT_FORMATS),
+},
+{
+	.name = "ssp1-port",
+	.playback = SOF_DAI_STREAM("ssp1 Tx", 1, 8,
+				   SNDRV_PCM_RATE_8000_192000, BYT_FORMATS),
+	.capture = SOF_DAI_STREAM("ssp1 Rx", 1, 8,
+				  SNDRV_PCM_RATE_8000_192000, BYT_FORMATS),
+},
+{
+	.name = "ssp2-port",
+	.playback = SOF_DAI_STREAM("ssp2 Tx", 1, 8,
+				   SNDRV_PCM_RATE_8000_192000, BYT_FORMATS),
+	.capture = SOF_DAI_STREAM("ssp2 Rx", 1, 8,
+				  SNDRV_PCM_RATE_8000_192000, BYT_FORMATS),
+},
+{
+	.name = "ssp3-port",
+	.playback = SOF_DAI_STREAM("ssp3 Tx", 1, 8,
+				   SNDRV_PCM_RATE_8000_192000, BYT_FORMATS),
+	.capture = SOF_DAI_STREAM("ssp3 Rx", 1, 8,
+				  SNDRV_PCM_RATE_8000_192000, BYT_FORMATS),
+},
+{
+	.name = "ssp4-port",
+	.playback = SOF_DAI_STREAM("ssp4 Tx", 1, 8,
+				   SNDRV_PCM_RATE_8000_192000, BYT_FORMATS),
+	.capture = SOF_DAI_STREAM("ssp4 Rx", 1, 8,
+				  SNDRV_PCM_RATE_8000_192000, BYT_FORMATS),
+},
+{
+	.name = "ssp5-port",
+	.playback = SOF_DAI_STREAM("ssp5 Tx", 1, 8,
+				   SNDRV_PCM_RATE_8000_192000, BYT_FORMATS),
+	.capture = SOF_DAI_STREAM("ssp5 Rx", 1, 8,
+				  SNDRV_PCM_RATE_8000_192000, BYT_FORMATS),
+},
+};
+
+/* baytrail ops */
+struct snd_sof_dsp_ops sof_byt_ops = {
+	/* device init */
+	.probe		= byt_probe,
+
+	/* DSP core boot / reset */
+	.run		= byt_run,
+	.reset		= byt_reset,
+
+	/* Register IO */
+	.write		= sof_io_write,
+	.read		= sof_io_read,
+	.write64	= sof_io_write64,
+	.read64		= sof_io_read64,
+
+	/* Block IO */
+	.block_read	= sof_block_read,
+	.block_write	= sof_block_write,
+
+	/* doorbell */
+	.irq_handler	= byt_irq_handler,
+	.irq_thread	= byt_irq_thread,
+
+	/* mailbox */
+	.mailbox_read	= sof_mailbox_read,
+	.mailbox_write	= sof_mailbox_write,
+
+	/* ipc */
+	.send_msg	= byt_send_msg,
+	.get_reply	= byt_get_reply,
+	.fw_ready	= byt_fw_ready,
+	.is_ready	= byt_is_ready,
+	.cmd_done	= byt_cmd_done,
+
+	/* debug */
+	.debug_map	= byt_debugfs,
+	.debug_map_count	= ARRAY_SIZE(byt_debugfs),
+	.dbg_dump	= byt_dump,
+
+	/* module loading */
+	.load_module	= snd_sof_parse_module_memcpy,
+
+	/*Firmware loading */
+	.load_firmware	= snd_sof_load_firmware_memcpy,
+
+	/* DAI drivers */
+	.drv = byt_dai,
+	.num_drv = 3, /* we have only 3 SSPs on byt*/
+};
+EXPORT_SYMBOL(sof_byt_ops);
+
+/* cherrytrail and braswell ops */
+struct snd_sof_dsp_ops sof_cht_ops = {
+	/* device init */
+	.probe		= byt_probe,
+
+	/* DSP core boot / reset */
+	.run		= byt_run,
+	.reset		= byt_reset,
+
+	/* Register IO */
+	.write		= sof_io_write,
+	.read		= sof_io_read,
+	.write64	= sof_io_write64,
+	.read64		= sof_io_read64,
+
+	/* Block IO */
+	.block_read	= sof_block_read,
+	.block_write	= sof_block_write,
+
+	/* doorbell */
+	.irq_handler	= byt_irq_handler,
+	.irq_thread	= byt_irq_thread,
+
+	/* mailbox */
+	.mailbox_read	= sof_mailbox_read,
+	.mailbox_write	= sof_mailbox_write,
+
+	/* ipc */
+	.send_msg	= byt_send_msg,
+	.get_reply	= byt_get_reply,
+	.fw_ready	= byt_fw_ready,
+	.is_ready	= byt_is_ready,
+	.cmd_done	= byt_cmd_done,
+
+	/* debug */
+	.debug_map	= cht_debugfs,
+	.debug_map_count	= ARRAY_SIZE(cht_debugfs),
+	.dbg_dump	= byt_dump,
+
+	/* module loading */
+	.load_module	= snd_sof_parse_module_memcpy,
+
+	/*Firmware loading */
+	.load_firmware	= snd_sof_load_firmware_memcpy,
+
+	/* DAI drivers */
+	.drv = byt_dai,
+	/* all 6 SSPs may be available for cherrytrail */
+	.num_drv = ARRAY_SIZE(byt_dai),
+};
+EXPORT_SYMBOL(sof_cht_ops);
+
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/sound/soc/sof/intel/shim.h b/sound/soc/sof/intel/shim.h
new file mode 100644
index 000000000000..2fdcb2d262f4
--- /dev/null
+++ b/sound/soc/sof/intel/shim.h
@@ -0,0 +1,159 @@ 
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
+/*
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * Copyright(c) 2017 Intel Corporation. All rights reserved.
+ *
+ * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
+ */
+
+#ifndef __SOF_INTEL_SHIM_H
+#define __SOF_INTEL_SHIM_H
+
+/*
+ * SHIM registers for BYT, BSW, CHT, HSW, BDW
+ */
+
+#define SHIM_CSR		(SHIM_OFFSET + 0x00)
+#define SHIM_PISR		(SHIM_OFFSET + 0x08)
+#define SHIM_PIMR		(SHIM_OFFSET + 0x10)
+#define SHIM_ISRX		(SHIM_OFFSET + 0x18)
+#define SHIM_ISRD		(SHIM_OFFSET + 0x20)
+#define SHIM_IMRX		(SHIM_OFFSET + 0x28)
+#define SHIM_IMRD		(SHIM_OFFSET + 0x30)
+#define SHIM_IPCX		(SHIM_OFFSET + 0x38)
+#define SHIM_IPCD		(SHIM_OFFSET + 0x40)
+#define SHIM_ISRSC		(SHIM_OFFSET + 0x48)
+#define SHIM_ISRLPESC		(SHIM_OFFSET + 0x50)
+#define SHIM_IMRSC		(SHIM_OFFSET + 0x58)
+#define SHIM_IMRLPESC		(SHIM_OFFSET + 0x60)
+#define SHIM_IPCSC		(SHIM_OFFSET + 0x68)
+#define SHIM_IPCLPESC		(SHIM_OFFSET + 0x70)
+#define SHIM_CLKCTL		(SHIM_OFFSET + 0x78)
+#define SHIM_CSR2		(SHIM_OFFSET + 0x80)
+#define SHIM_LTRC		(SHIM_OFFSET + 0xE0)
+#define SHIM_HMDC		(SHIM_OFFSET + 0xE8)
+
+#define SHIM_PWMCTRL		0x1000
+
+/*
+ * SST SHIM register bits for BYT, BSW, CHT HSW, BDW
+ * Register bit naming and functionaility can differ between devices.
+ */
+
+/* CSR / CS */
+#define SHIM_CSR_RST		BIT(1)
+#define SHIM_CSR_SBCS0		BIT(2)
+#define SHIM_CSR_SBCS1		BIT(3)
+#define SHIM_CSR_DCS(x)		((x) << 4)
+#define SHIM_CSR_DCS_MASK	(0x7 << 4)
+#define SHIM_CSR_STALL		BIT(10)
+#define SHIM_CSR_S0IOCS		BIT(21)
+#define SHIM_CSR_S1IOCS		BIT(23)
+#define SHIM_CSR_LPCS		BIT(31)
+#define SHIM_CSR_24MHZ_LPCS \
+	(SHIM_CSR_SBCS0 | SHIM_CSR_SBCS1 | SHIM_CSR_LPCS)
+#define SHIM_CSR_24MHZ_NO_LPCS	(SHIM_CSR_SBCS0 | SHIM_CSR_SBCS1)
+#define SHIM_BYT_CSR_RST	BIT(0)
+#define SHIM_BYT_CSR_VECTOR_SEL	BIT(1)
+#define SHIM_BYT_CSR_STALL	BIT(2)
+#define SHIM_BYT_CSR_PWAITMODE	BIT(3)
+
+/*  ISRX / ISC */
+#define SHIM_ISRX_BUSY		BIT(1)
+#define SHIM_ISRX_DONE		BIT(0)
+#define SHIM_BYT_ISRX_REQUEST	BIT(1)
+
+/*  ISRD / ISD */
+#define SHIM_ISRD_BUSY		BIT(1)
+#define SHIM_ISRD_DONE		BIT(0)
+
+/* IMRX / IMC */
+#define SHIM_IMRX_BUSY		BIT(1)
+#define SHIM_IMRX_DONE		BIT(0)
+#define SHIM_BYT_IMRX_REQUEST	BIT(1)
+
+/* IMRD / IMD */
+#define SHIM_IMRD_DONE		BIT(0)
+#define SHIM_IMRD_BUSY		BIT(1)
+#define SHIM_IMRD_SSP0		BIT(16)
+#define SHIM_IMRD_DMAC0		BIT(21)
+#define SHIM_IMRD_DMAC1		BIT(22)
+#define SHIM_IMRD_DMAC		(SHIM_IMRD_DMAC0 | SHIM_IMRD_DMAC1)
+
+/*  IPCX / IPCC */
+#define	SHIM_IPCX_DONE		BIT(30)
+#define	SHIM_IPCX_BUSY		BIT(31)
+#define SHIM_BYT_IPCX_DONE	BIT_ULL(62)
+#define SHIM_BYT_IPCX_BUSY	BIT_ULL(63)
+
+/*  IPCD */
+#define	SHIM_IPCD_DONE		BIT(30)
+#define	SHIM_IPCD_BUSY		BIT(31)
+#define SHIM_BYT_IPCD_DONE	BIT_ULL(62)
+#define SHIM_BYT_IPCD_BUSY	BIT_ULL(63)
+
+/* CLKCTL */
+#define SHIM_CLKCTL_SMOS(x)	((x) << 24)
+#define SHIM_CLKCTL_MASK	(3 << 24)
+#define SHIM_CLKCTL_DCPLCG	BIT(18)
+#define SHIM_CLKCTL_SCOE1	BIT(17)
+#define SHIM_CLKCTL_SCOE0	BIT(16)
+
+/* CSR2 / CS2 */
+#define SHIM_CSR2_SDFD_SSP0	BIT(1)
+#define SHIM_CSR2_SDFD_SSP1	BIT(2)
+
+/* LTRC */
+#define SHIM_LTRC_VAL(x)	((x) << 0)
+
+/* HMDC */
+#define SHIM_HMDC_HDDA0(x)	((x) << 0)
+#define SHIM_HMDC_HDDA1(x)	((x) << 7)
+#define SHIM_HMDC_HDDA_E0_CH0	1
+#define SHIM_HMDC_HDDA_E0_CH1	2
+#define SHIM_HMDC_HDDA_E0_CH2	4
+#define SHIM_HMDC_HDDA_E0_CH3	8
+#define SHIM_HMDC_HDDA_E1_CH0	SHIM_HMDC_HDDA1(SHIM_HMDC_HDDA_E0_CH0)
+#define SHIM_HMDC_HDDA_E1_CH1	SHIM_HMDC_HDDA1(SHIM_HMDC_HDDA_E0_CH1)
+#define SHIM_HMDC_HDDA_E1_CH2	SHIM_HMDC_HDDA1(SHIM_HMDC_HDDA_E0_CH2)
+#define SHIM_HMDC_HDDA_E1_CH3	SHIM_HMDC_HDDA1(SHIM_HMDC_HDDA_E0_CH3)
+#define SHIM_HMDC_HDDA_E0_ALLCH	\
+	(SHIM_HMDC_HDDA_E0_CH0 | SHIM_HMDC_HDDA_E0_CH1 | \
+	 SHIM_HMDC_HDDA_E0_CH2 | SHIM_HMDC_HDDA_E0_CH3)
+#define SHIM_HMDC_HDDA_E1_ALLCH	\
+	(SHIM_HMDC_HDDA_E1_CH0 | SHIM_HMDC_HDDA_E1_CH1 | \
+	 SHIM_HMDC_HDDA_E1_CH2 | SHIM_HMDC_HDDA_E1_CH3)
+
+/* Audio DSP PCI registers */
+#define PCI_VDRTCTL0		0xa0
+#define PCI_VDRTCTL1		0xa4
+#define PCI_VDRTCTL2		0xa8
+#define PCI_VDRTCTL3		0xaC
+
+/* VDRTCTL0 */
+#define PCI_VDRTCL0_D3PGD		BIT(0)
+#define PCI_VDRTCL0_D3SRAMPGD		BIT(1)
+#define PCI_VDRTCL0_DSRAMPGE_SHIFT	12
+#define PCI_VDRTCL0_DSRAMPGE_MASK	GENMASK(PCI_VDRTCL0_DSRAMPGE_SHIFT + 19,\
+						PCI_VDRTCL0_DSRAMPGE_SHIFT)
+#define PCI_VDRTCL0_ISRAMPGE_SHIFT	2
+#define PCI_VDRTCL0_ISRAMPGE_MASK	GENMASK(PCI_VDRTCL0_ISRAMPGE_SHIFT + 9,\
+						PCI_VDRTCL0_ISRAMPGE_SHIFT)
+
+/* VDRTCTL2 */
+#define PCI_VDRTCL2_DCLCGE		BIT(1)
+#define PCI_VDRTCL2_DTCGE		BIT(10)
+#define PCI_VDRTCL2_APLLSE_MASK		BIT(31)
+
+/* PMCS */
+#define PCI_PMCS		0x84
+#define PCI_PMCS_PS_MASK	0x3
+
+extern struct snd_sof_dsp_ops sof_byt_ops;
+extern struct snd_sof_dsp_ops sof_cht_ops;
+extern struct snd_sof_dsp_ops sof_hsw_ops;
+extern struct snd_sof_dsp_ops sof_bdw_ops;
+
+#endif