summaryrefslogtreecommitdiffstats
path: root/sound/soc/sof/ops.h
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-08-23 13:28:57 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2026-08-23 13:28:57 -0700
commit4352b8aee98005853aa63f57d6377282de17a33f (patch)
tree27614d7a9ef05c32d089004e104364ce42324837 /sound/soc/sof/ops.h
downloadlinux-stable-4352b8aee98005853aa63f57d6377282de17a33f.tar.gz
linux-stable-4352b8aee98005853aa63f57d6377282de17a33f.zip
Merge tag 'i3c/for-7.3' of git://git.kernel.org/pub/scm/linux/kernel/git/i3c/linuxgrafted
Pull I3C updates from Alexandre Belloni: "A new driver this cycle, for the AMD AXI I3C controller. There are also new features such as IBI wakeup support, SETAASA device discovery and ACPI support for the the DAA methods, meaning we can now communicate with the SPD devices on DDR5 modules. New driver: - AMD AXI I3C master controller Subsystem: - I3C Common Command Code (CCC) handling improvements, especially around GET CCCs - SETAASA device discovery support - ACPI support for all existing DAA methods like SETDASA, SETNEWDA as well as I2C devices on I3C bus - IBI-based wakeup support Drivers: - dw: SETAASA support - mipi-i3c-hci: advertise IBI wakeup capability, AMD_PT I3C controller support, PIO queue management support for HCI v1.2 - renesas: improve suspend to RAM support, add runtime PM support" * tag 'i3c/for-7.3' of git://git.kernel.org/pub/scm/linux/kernel/git/i3c/linux: (70 commits) i3c: dw: reduce do_daa time if there's no client i3c: mipi-i3c-hci: Add support for AMD_PT I3C controller i3c: mipi-i3c-hci: Add PIO queue management support for HCI v1.2 i3c: mipi-i3c-hci: Fix missing STAT_IBI_STATUS_THLD in PIO mode i3c: dw: rename "pclk" to "apb" to match dt-binding i3c: dw: make struct dw_i3c_cmd smaller i3c: dw: use COMMAND_PORT_TRANSFER_ARG instead of hardcoding i3c: renesas: Don't register devices when ENTDAA times out i3c: master: dw-i3c-master: fix OD timing for first broadcast i3c: mipi-i3c-hci: Advertise IBI wakeup capability i3c: mipi-i3c-hci: Factor out i3c_hci_sysdev() i3c: mipi-i3c-hci-pci: Propagate I3C wakeup requirements to PCI i3c: master: Reject IBI requests from non-IBI-capable devices i3c: master: Add helper to query bus wakeup requirements i3c: master: Report wakeup events for IBIs i3c: master: Support IBI-based wakeup capability i3c: master: Fix potential UAF in i3c_device_match() i3c: master: Fix potential UAF in i3c_device_uevent() i3c: Make dev->desc locking assumptions explicit i3c: master: Fix use-after-free of master->this ...
Diffstat (limited to 'sound/soc/sof/ops.h')
-rw-r--r--sound/soc/sof/ops.h659
1 files changed, 659 insertions, 0 deletions
diff --git a/sound/soc/sof/ops.h b/sound/soc/sof/ops.h
new file mode 100644
index 000000000..72af1f4ff
--- /dev/null
+++ b/sound/soc/sof/ops.h
@@ -0,0 +1,659 @@
+/* SPDX-License-Identifier: (GPL-2.0-only 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
+ *
+ * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
+ */
+
+#ifndef __SOUND_SOC_SOF_IO_H
+#define __SOUND_SOC_SOF_IO_H
+
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <sound/pcm.h>
+#include "sof-priv.h"
+
+#define sof_ops(sdev) \
+ ((sdev)->pdata->desc->ops)
+
+static inline int sof_ops_init(struct snd_sof_dev *sdev)
+{
+ if (sdev->pdata->desc->ops_init)
+ return sdev->pdata->desc->ops_init(sdev);
+
+ return 0;
+}
+
+static inline void sof_ops_free(struct snd_sof_dev *sdev)
+{
+ if (sdev->pdata->desc->ops_free)
+ sdev->pdata->desc->ops_free(sdev);
+}
+
+/* Mandatory operations are verified during probing */
+
+/* init */
+static inline int snd_sof_probe_early(struct snd_sof_dev *sdev)
+{
+ if (sof_ops(sdev)->probe_early)
+ return sof_ops(sdev)->probe_early(sdev);
+
+ return 0;
+}
+
+static inline int snd_sof_probe(struct snd_sof_dev *sdev)
+{
+ return sof_ops(sdev)->probe(sdev);
+}
+
+static inline void snd_sof_remove(struct snd_sof_dev *sdev)
+{
+ if (sof_ops(sdev)->remove)
+ sof_ops(sdev)->remove(sdev);
+}
+
+static inline void snd_sof_remove_late(struct snd_sof_dev *sdev)
+{
+ if (sof_ops(sdev)->remove_late)
+ sof_ops(sdev)->remove_late(sdev);
+}
+
+static inline int snd_sof_shutdown(struct snd_sof_dev *sdev)
+{
+ if (sof_ops(sdev)->shutdown)
+ return sof_ops(sdev)->shutdown(sdev);
+
+ return 0;
+}
+
+/* control */
+
+/*
+ * snd_sof_dsp_run returns the core mask of the cores that are available
+ * after successful fw boot
+ */
+static inline int snd_sof_dsp_run(struct snd_sof_dev *sdev)
+{
+ return sof_ops(sdev)->run(sdev);
+}
+
+static inline int snd_sof_dsp_stall(struct snd_sof_dev *sdev, unsigned int core_mask)
+{
+ if (sof_ops(sdev)->stall)
+ return sof_ops(sdev)->stall(sdev, core_mask);
+
+ return 0;
+}
+
+static inline int snd_sof_dsp_reset(struct snd_sof_dev *sdev)
+{
+ if (sof_ops(sdev)->reset)
+ return sof_ops(sdev)->reset(sdev);
+
+ return 0;
+}
+
+/* dsp core get/put */
+static inline int snd_sof_dsp_core_get(struct snd_sof_dev *sdev, int core)
+{
+ if (core > sdev->num_cores - 1) {
+ dev_err(sdev->dev, "invalid core id: %d for num_cores: %d\n", core,
+ sdev->num_cores);
+ return -EINVAL;
+ }
+
+ if (sof_ops(sdev)->core_get) {
+ int ret;
+
+ /* if current ref_count is > 0, increment it and return */
+ if (sdev->dsp_core_ref_count[core] > 0) {
+ sdev->dsp_core_ref_count[core]++;
+ return 0;
+ }
+
+ /* power up the core */
+ ret = sof_ops(sdev)->core_get(sdev, core);
+ if (ret < 0)
+ return ret;
+
+ /* increment ref_count */
+ sdev->dsp_core_ref_count[core]++;
+
+ /* and update enabled_cores_mask */
+ sdev->enabled_cores_mask |= BIT(core);
+
+ dev_dbg(sdev->dev, "Core %d powered up\n", core);
+ }
+
+ return 0;
+}
+
+static inline int snd_sof_dsp_core_put(struct snd_sof_dev *sdev, int core)
+{
+ if (core > sdev->num_cores - 1) {
+ dev_err(sdev->dev, "invalid core id: %d for num_cores: %d\n", core,
+ sdev->num_cores);
+ return -EINVAL;
+ }
+
+ if (sof_ops(sdev)->core_put) {
+ int ret;
+
+ /* decrement ref_count and return if it is > 0 */
+ if (--(sdev->dsp_core_ref_count[core]) > 0)
+ return 0;
+
+ /* power down the core */
+ ret = sof_ops(sdev)->core_put(sdev, core);
+ if (ret < 0)
+ return ret;
+
+ /* and update enabled_cores_mask */
+ sdev->enabled_cores_mask &= ~BIT(core);
+
+ dev_dbg(sdev->dev, "Core %d powered down\n", core);
+ }
+
+ return 0;
+}
+
+/* pre/post fw load */
+static inline int snd_sof_dsp_pre_fw_run(struct snd_sof_dev *sdev)
+{
+ if (sof_ops(sdev)->pre_fw_run)
+ return sof_ops(sdev)->pre_fw_run(sdev);
+
+ return 0;
+}
+
+static inline int snd_sof_dsp_post_fw_run(struct snd_sof_dev *sdev)
+{
+ if (sof_ops(sdev)->post_fw_run)
+ return sof_ops(sdev)->post_fw_run(sdev);
+
+ return 0;
+}
+
+/* parse platform specific extended manifest */
+static inline int snd_sof_dsp_parse_platform_ext_manifest(struct snd_sof_dev *sdev,
+ const struct sof_ext_man_elem_header *hdr)
+{
+ if (sof_ops(sdev)->parse_platform_ext_manifest)
+ return sof_ops(sdev)->parse_platform_ext_manifest(sdev, hdr);
+
+ return 0;
+}
+
+/* misc */
+
+/**
+ * snd_sof_dsp_get_bar_index - Maps a section type with a BAR index
+ *
+ * @sdev: sof device
+ * @type: section type as described by snd_sof_fw_blk_type
+ *
+ * Returns the corresponding BAR index (a positive integer) or -EINVAL
+ * in case there is no mapping
+ */
+static inline int snd_sof_dsp_get_bar_index(struct snd_sof_dev *sdev, u32 type)
+{
+ if (sof_ops(sdev)->get_bar_index)
+ return sof_ops(sdev)->get_bar_index(sdev, type);
+
+ return sdev->mmio_bar;
+}
+
+static inline int snd_sof_dsp_get_mailbox_offset(struct snd_sof_dev *sdev)
+{
+ if (sof_ops(sdev)->get_mailbox_offset)
+ return sof_ops(sdev)->get_mailbox_offset(sdev);
+
+ dev_err(sdev->dev, "error: %s not defined\n", __func__);
+ return -EOPNOTSUPP;
+}
+
+static inline int snd_sof_dsp_get_window_offset(struct snd_sof_dev *sdev,
+ u32 id)
+{
+ if (sof_ops(sdev)->get_window_offset)
+ return sof_ops(sdev)->get_window_offset(sdev, id);
+
+ dev_err(sdev->dev, "error: %s not defined\n", __func__);
+ return -EOPNOTSUPP;
+}
+/* power management */
+static inline int snd_sof_dsp_resume(struct snd_sof_dev *sdev)
+{
+ if (sof_ops(sdev)->resume)
+ return sof_ops(sdev)->resume(sdev);
+
+ return 0;
+}
+
+static inline int snd_sof_dsp_suspend(struct snd_sof_dev *sdev,
+ u32 target_state)
+{
+ if (sof_ops(sdev)->suspend)
+ return sof_ops(sdev)->suspend(sdev, target_state);
+
+ return 0;
+}
+
+static inline int snd_sof_dsp_runtime_resume(struct snd_sof_dev *sdev)
+{
+ if (sof_ops(sdev)->runtime_resume)
+ return sof_ops(sdev)->runtime_resume(sdev);
+
+ return 0;
+}
+
+static inline int snd_sof_dsp_runtime_suspend(struct snd_sof_dev *sdev)
+{
+ if (sof_ops(sdev)->runtime_suspend)
+ return sof_ops(sdev)->runtime_suspend(sdev);
+
+ return 0;
+}
+
+static inline int snd_sof_dsp_runtime_idle(struct snd_sof_dev *sdev)
+{
+ if (sof_ops(sdev)->runtime_idle)
+ return sof_ops(sdev)->runtime_idle(sdev);
+
+ return 0;
+}
+
+static inline int snd_sof_dsp_hw_params_upon_resume(struct snd_sof_dev *sdev)
+{
+ if (sof_ops(sdev)->set_hw_params_upon_resume)
+ return sof_ops(sdev)->set_hw_params_upon_resume(sdev);
+ return 0;
+}
+
+static inline int snd_sof_dsp_set_clk(struct snd_sof_dev *sdev, u32 freq)
+{
+ if (sof_ops(sdev)->set_clk)
+ return sof_ops(sdev)->set_clk(sdev, freq);
+
+ return 0;
+}
+
+static inline int
+snd_sof_dsp_set_power_state(struct snd_sof_dev *sdev,
+ const struct sof_dsp_power_state *target_state)
+{
+ guard(mutex)(&sdev->power_state_access);
+
+ if (sof_ops(sdev)->set_power_state)
+ return sof_ops(sdev)->set_power_state(sdev, target_state);
+
+ return 0;
+}
+
+/* debug */
+void snd_sof_dsp_dbg_dump(struct snd_sof_dev *sdev, const char *msg, u32 flags);
+
+static inline int snd_sof_debugfs_add_region_item(struct snd_sof_dev *sdev,
+ enum snd_sof_fw_blk_type blk_type, u32 offset, size_t size,
+ const char *name, enum sof_debugfs_access_type access_type)
+{
+ if (sof_ops(sdev) && sof_ops(sdev)->debugfs_add_region_item)
+ return sof_ops(sdev)->debugfs_add_region_item(sdev, blk_type, offset,
+ size, name, access_type);
+
+ return 0;
+}
+
+/* register IO */
+static inline void snd_sof_dsp_write8(struct snd_sof_dev *sdev, u32 bar,
+ u32 offset, u8 value)
+{
+ if (sof_ops(sdev)->write8)
+ sof_ops(sdev)->write8(sdev, sdev->bar[bar] + offset, value);
+ else
+ writeb(value, sdev->bar[bar] + offset);
+}
+
+static inline void snd_sof_dsp_write(struct snd_sof_dev *sdev, u32 bar,
+ u32 offset, u32 value)
+{
+ if (sof_ops(sdev)->write)
+ sof_ops(sdev)->write(sdev, sdev->bar[bar] + offset, value);
+ else
+ writel(value, sdev->bar[bar] + offset);
+}
+
+static inline void snd_sof_dsp_write64(struct snd_sof_dev *sdev, u32 bar,
+ u32 offset, u64 value)
+{
+ if (sof_ops(sdev)->write64)
+ sof_ops(sdev)->write64(sdev, sdev->bar[bar] + offset, value);
+ else
+ writeq(value, sdev->bar[bar] + offset);
+}
+
+static inline u8 snd_sof_dsp_read8(struct snd_sof_dev *sdev, u32 bar,
+ u32 offset)
+{
+ if (sof_ops(sdev)->read8)
+ return sof_ops(sdev)->read8(sdev, sdev->bar[bar] + offset);
+ else
+ return readb(sdev->bar[bar] + offset);
+}
+
+static inline u32 snd_sof_dsp_read(struct snd_sof_dev *sdev, u32 bar,
+ u32 offset)
+{
+ if (sof_ops(sdev)->read)
+ return sof_ops(sdev)->read(sdev, sdev->bar[bar] + offset);
+ else
+ return readl(sdev->bar[bar] + offset);
+}
+
+static inline u64 snd_sof_dsp_read64(struct snd_sof_dev *sdev, u32 bar,
+ u32 offset)
+{
+ if (sof_ops(sdev)->read64)
+ return sof_ops(sdev)->read64(sdev, sdev->bar[bar] + offset);
+ else
+ return readq(sdev->bar[bar] + offset);
+}
+
+static inline void snd_sof_dsp_update8(struct snd_sof_dev *sdev, u32 bar,
+ u32 offset, u8 mask, u8 value)
+{
+ u8 reg;
+
+ reg = snd_sof_dsp_read8(sdev, bar, offset);
+ reg &= ~mask;
+ reg |= value;
+ snd_sof_dsp_write8(sdev, bar, offset, reg);
+}
+
+/* block IO */
+static inline int snd_sof_dsp_block_read(struct snd_sof_dev *sdev,
+ enum snd_sof_fw_blk_type blk_type,
+ u32 offset, void *dest, size_t bytes)
+{
+ return sof_ops(sdev)->block_read(sdev, blk_type, offset, dest, bytes);
+}
+
+static inline int snd_sof_dsp_block_write(struct snd_sof_dev *sdev,
+ enum snd_sof_fw_blk_type blk_type,
+ u32 offset, void *src, size_t bytes)
+{
+ return sof_ops(sdev)->block_write(sdev, blk_type, offset, src, bytes);
+}
+
+/* mailbox IO */
+static inline void snd_sof_dsp_mailbox_read(struct snd_sof_dev *sdev,
+ u32 offset, void *dest, size_t bytes)
+{
+ if (sof_ops(sdev)->mailbox_read)
+ sof_ops(sdev)->mailbox_read(sdev, offset, dest, bytes);
+}
+
+static inline void snd_sof_dsp_mailbox_write(struct snd_sof_dev *sdev,
+ u32 offset, void *src, size_t bytes)
+{
+ if (sof_ops(sdev)->mailbox_write)
+ sof_ops(sdev)->mailbox_write(sdev, offset, src, bytes);
+}
+
+/* ipc */
+static inline int snd_sof_dsp_send_msg(struct snd_sof_dev *sdev,
+ struct snd_sof_ipc_msg *msg)
+{
+ return sof_ops(sdev)->send_msg(sdev, msg);
+}
+
+/* host PCM ops */
+static inline int
+snd_sof_pcm_platform_open(struct snd_sof_dev *sdev,
+ struct snd_pcm_substream *substream)
+{
+ if (sof_ops(sdev) && sof_ops(sdev)->pcm_open)
+ return sof_ops(sdev)->pcm_open(sdev, substream);
+
+ return 0;
+}
+
+/* disconnect pcm substream to a host stream */
+static inline int
+snd_sof_pcm_platform_close(struct snd_sof_dev *sdev,
+ struct snd_pcm_substream *substream)
+{
+ if (sof_ops(sdev) && sof_ops(sdev)->pcm_close)
+ return sof_ops(sdev)->pcm_close(sdev, substream);
+
+ return 0;
+}
+
+/* host stream hw params */
+static inline int
+snd_sof_pcm_platform_hw_params(struct snd_sof_dev *sdev,
+ struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_sof_platform_stream_params *platform_params)
+{
+ if (sof_ops(sdev) && sof_ops(sdev)->pcm_hw_params)
+ return sof_ops(sdev)->pcm_hw_params(sdev, substream, params,
+ platform_params);
+
+ return 0;
+}
+
+/* host stream hw free */
+static inline int
+snd_sof_pcm_platform_hw_free(struct snd_sof_dev *sdev,
+ struct snd_pcm_substream *substream)
+{
+ if (sof_ops(sdev) && sof_ops(sdev)->pcm_hw_free)
+ return sof_ops(sdev)->pcm_hw_free(sdev, substream);
+
+ return 0;
+}
+
+/* host stream trigger */
+static inline int
+snd_sof_pcm_platform_trigger(struct snd_sof_dev *sdev,
+ struct snd_pcm_substream *substream, int cmd)
+{
+ if (sof_ops(sdev) && sof_ops(sdev)->pcm_trigger)
+ return sof_ops(sdev)->pcm_trigger(sdev, substream, cmd);
+
+ return 0;
+}
+
+/* Firmware loading */
+static inline int snd_sof_load_firmware(struct snd_sof_dev *sdev)
+{
+ dev_dbg(sdev->dev, "loading firmware\n");
+
+ return sof_ops(sdev)->load_firmware(sdev);
+}
+
+/* host DSP message data */
+static inline int snd_sof_ipc_msg_data(struct snd_sof_dev *sdev,
+ struct snd_sof_pcm_stream *sps,
+ void *p, size_t sz)
+{
+ return sof_ops(sdev)->ipc_msg_data(sdev, sps, p, sz);
+}
+/* host side configuration of the stream's data offset in stream mailbox area */
+static inline int
+snd_sof_set_stream_data_offset(struct snd_sof_dev *sdev,
+ struct snd_sof_pcm_stream *sps,
+ size_t posn_offset)
+{
+ if (sof_ops(sdev) && sof_ops(sdev)->set_stream_data_offset)
+ return sof_ops(sdev)->set_stream_data_offset(sdev, sps,
+ posn_offset);
+
+ return 0;
+}
+
+/* host stream pointer */
+static inline snd_pcm_uframes_t
+snd_sof_pcm_platform_pointer(struct snd_sof_dev *sdev,
+ struct snd_pcm_substream *substream)
+{
+ if (sof_ops(sdev) && sof_ops(sdev)->pcm_pointer)
+ return sof_ops(sdev)->pcm_pointer(sdev, substream);
+
+ return 0;
+}
+
+/* pcm ack */
+static inline int snd_sof_pcm_platform_ack(struct snd_sof_dev *sdev,
+ struct snd_pcm_substream *substream)
+{
+ if (sof_ops(sdev) && sof_ops(sdev)->pcm_ack)
+ return sof_ops(sdev)->pcm_ack(sdev, substream);
+
+ return 0;
+}
+
+static inline u64
+snd_sof_pcm_get_dai_frame_counter(struct snd_sof_dev *sdev,
+ struct snd_soc_component *component,
+ struct snd_pcm_substream *substream)
+{
+ if (sof_ops(sdev) && sof_ops(sdev)->get_dai_frame_counter)
+ return sof_ops(sdev)->get_dai_frame_counter(sdev, component,
+ substream);
+
+ return 0;
+}
+
+static inline u64
+snd_sof_pcm_get_host_byte_counter(struct snd_sof_dev *sdev,
+ struct snd_soc_component *component,
+ struct snd_pcm_substream *substream)
+{
+ if (sof_ops(sdev) && sof_ops(sdev)->get_host_byte_counter)
+ return sof_ops(sdev)->get_host_byte_counter(sdev, component,
+ substream);
+
+ return 0;
+}
+
+/* machine driver */
+static inline int
+snd_sof_machine_register(struct snd_sof_dev *sdev, void *pdata)
+{
+ if (sof_ops(sdev) && sof_ops(sdev)->machine_register)
+ return sof_ops(sdev)->machine_register(sdev, pdata);
+
+ return 0;
+}
+
+static inline void
+snd_sof_machine_unregister(struct snd_sof_dev *sdev, void *pdata)
+{
+ if (sof_ops(sdev) && sof_ops(sdev)->machine_unregister)
+ sof_ops(sdev)->machine_unregister(sdev, pdata);
+}
+
+static inline struct snd_soc_acpi_mach *
+snd_sof_machine_select(struct snd_sof_dev *sdev)
+{
+ if (sof_ops(sdev) && sof_ops(sdev)->machine_select)
+ return sof_ops(sdev)->machine_select(sdev);
+
+ return NULL;
+}
+
+static inline void
+snd_sof_set_mach_params(struct snd_soc_acpi_mach *mach,
+ struct snd_sof_dev *sdev)
+{
+ if (sof_ops(sdev) && sof_ops(sdev)->set_mach_params)
+ sof_ops(sdev)->set_mach_params(mach, sdev);
+}
+
+static inline bool
+snd_sof_is_chain_dma_supported(struct snd_sof_dev *sdev, u32 dai_type)
+{
+ if (sof_ops(sdev) && sof_ops(sdev)->is_chain_dma_supported)
+ return sof_ops(sdev)->is_chain_dma_supported(sdev, dai_type);
+
+ return false;
+}
+
+/**
+ * snd_sof_dsp_register_poll_timeout - Periodically poll an address
+ * until a condition is met or a timeout occurs
+ * @op: accessor function (takes @addr as its only argument)
+ * @addr: Address to poll
+ * @val: Variable to read the value into
+ * @cond: Break condition (usually involving @val)
+ * @sleep_us: Maximum time to sleep between reads in us (0 tight-loops). Please
+ * read usleep_range() function description for details and
+ * limitations.
+ * @timeout_us: Timeout in us, 0 means never timeout
+ *
+ * Returns: 0 on success and -ETIMEDOUT upon a timeout. In either
+ * case, the last read value at @addr is stored in @val. Must not
+ * be called from atomic context if sleep_us or timeout_us are used.
+ *
+ * This is modelled after the readx_poll_timeout macros in linux/iopoll.h.
+ */
+#define snd_sof_dsp_read_poll_timeout(sdev, bar, offset, val, cond, sleep_us, timeout_us) \
+({ \
+ u64 __timeout_us = (timeout_us); \
+ unsigned long __sleep_us = (sleep_us); \
+ ktime_t __timeout = ktime_add_us(ktime_get(), __timeout_us); \
+ might_sleep_if((__sleep_us) != 0); \
+ for (;;) { \
+ (val) = snd_sof_dsp_read(sdev, bar, offset); \
+ if (cond) { \
+ dev_dbg(sdev->dev, \
+ "FW Poll Status: reg[%#x]=%#x successful\n", \
+ (offset), (val)); \
+ break; \
+ } \
+ if (__timeout_us && \
+ ktime_compare(ktime_get(), __timeout) > 0) { \
+ (val) = snd_sof_dsp_read(sdev, bar, offset); \
+ dev_dbg(sdev->dev, \
+ "FW Poll Status: reg[%#x]=%#x timedout\n", \
+ (offset), (val)); \
+ break; \
+ } \
+ if (__sleep_us) \
+ usleep_range((__sleep_us >> 2) + 1, __sleep_us); \
+ } \
+ (cond) ? 0 : -ETIMEDOUT; \
+})
+
+/* This is for registers bits with attribute RWC */
+bool snd_sof_pci_update_bits(struct snd_sof_dev *sdev, u32 offset,
+ u32 mask, u32 value);
+
+bool snd_sof_dsp_update_bits_unlocked(struct snd_sof_dev *sdev, u32 bar,
+ u32 offset, u32 mask, u32 value);
+
+bool snd_sof_dsp_update_bits64_unlocked(struct snd_sof_dev *sdev, u32 bar,
+ u32 offset, u64 mask, u64 value);
+
+bool snd_sof_dsp_update_bits(struct snd_sof_dev *sdev, u32 bar, u32 offset,
+ u32 mask, u32 value);
+
+bool snd_sof_dsp_update_bits64(struct snd_sof_dev *sdev, u32 bar,
+ u32 offset, u64 mask, u64 value);
+
+void snd_sof_dsp_update_bits_forced(struct snd_sof_dev *sdev, u32 bar,
+ u32 offset, u32 mask, u32 value);
+
+int snd_sof_dsp_register_poll(struct snd_sof_dev *sdev, u32 bar, u32 offset,
+ u32 mask, u32 target, u32 timeout_ms,
+ u32 interval_us);
+
+void snd_sof_dsp_panic(struct snd_sof_dev *sdev, u32 offset, bool non_recoverable);
+#endif