diff --git a/sound/soc/intel/avs/avs.h b/sound/soc/intel/avs/avs.h
index 9096f6c3d598..263ceb39d25d 100644
--- a/sound/soc/intel/avs/avs.h
+++ b/sound/soc/intel/avs/avs.h
@@ -11,6 +11,7 @@
 
 #include <linux/device.h>
 #include <linux/firmware.h>
+#include <linux/kfifo.h>
 #include <sound/hda_codec.h>
 #include <sound/hda_register.h>
 #include <sound/soc-component.h>
@@ -42,6 +43,10 @@ struct avs_dsp_ops {
 	int (* const load_basefw)(struct avs_dev *, struct firmware *);
 	int (* const load_lib)(struct avs_dev *, struct firmware *, u32);
 	int (* const transfer_mods)(struct avs_dev *, bool, struct avs_module_entry *, u32);
+	int (* const enable_logs)(struct avs_dev *, enum avs_log_enable, u32, u32, unsigned long,
+				  u32 *);
+	int (* const log_buffer_offset)(struct avs_dev *, u32);
+	int (* const log_buffer_status)(struct avs_dev *, union avs_notify_msg *);
 	int (* const coredump)(struct avs_dev *, union avs_notify_msg *);
 };
 
@@ -75,6 +80,16 @@ struct avs_fw_entry {
 	struct list_head node;
 };
 
+struct avs_debug {
+	struct kfifo trace_fifo;
+	spinlock_t fifo_lock;	/* serialize I/O for trace_fifo */
+	spinlock_t trace_lock;	/* serialize debug window I/O between each LOG_BUFFER_STATUS */
+	wait_queue_head_t trace_waitq;
+	u32 aging_timer_period;
+	u32 fifo_full_timer_period;
+	u32 logged_resources;	/* context dependent: core or library */
+};
+
 /*
  * struct avs_dev - Intel HD-Audio driver data
  *
@@ -115,6 +130,8 @@ struct avs_dev {
 	struct list_head path_list;
 	spinlock_t path_list_lock;
 	struct mutex path_mutex;
+
+	struct avs_debug dbg;
 };
 
 /* from hda_bus to avs_dev */
@@ -279,4 +296,19 @@ int avs_i2s_platform_register(struct avs_dev *adev, const char *name, unsigned l
 			      unsigned long *tdms);
 int avs_hda_platform_register(struct avs_dev *adev, const char *name);
 
+/* Firmware tracing helpers */
+
+unsigned int __kfifo_fromio_locked(struct kfifo *fifo, const void __iomem *src, unsigned int len,
+				   spinlock_t *lock);
+
+#define avs_log_buffer_size(adev) \
+	((adev)->fw_cfg.trace_log_bytes / (adev)->hw_cfg.dsp_cores)
+
+#define avs_log_buffer_addr(adev, core) \
+({ \
+	s32 __offset = avs_dsp_op(adev, log_buffer_offset, core); \
+	(__offset < 0) ? NULL : \
+			 (avs_sram_addr(adev, AVS_DEBUG_WINDOW) + __offset); \
+})
+
 #endif /* __SOUND_SOC_INTEL_AVS_H */
diff --git a/sound/soc/intel/avs/ipc.c b/sound/soc/intel/avs/ipc.c
index 98cdc05071fb..feb900ba1db9 100644
--- a/sound/soc/intel/avs/ipc.c
+++ b/sound/soc/intel/avs/ipc.c
@@ -140,6 +140,7 @@ static void avs_dsp_process_notification(struct avs_dev *adev, u64 header)
 		data_size = sizeof(struct avs_notify_res_data);
 		break;
 
+	case AVS_NOTIFY_LOG_BUFFER_STATUS:
 	case AVS_NOTIFY_EXCEPTION_CAUGHT:
 		break;
 
@@ -170,6 +171,10 @@ static void avs_dsp_process_notification(struct avs_dev *adev, u64 header)
 		complete(&adev->fw_ready);
 		break;
 
+	case AVS_NOTIFY_LOG_BUFFER_STATUS:
+		avs_dsp_op(adev, log_buffer_status, &msg);
+		break;
+
 	case AVS_NOTIFY_EXCEPTION_CAUGHT:
 		avs_dsp_exception_caught(adev, &msg);
 		break;
diff --git a/sound/soc/intel/avs/messages.c b/sound/soc/intel/avs/messages.c
index 004da166a943..3da33150aabf 100644
--- a/sound/soc/intel/avs/messages.c
+++ b/sound/soc/intel/avs/messages.c
@@ -677,6 +677,37 @@ int avs_ipc_get_modules_info(struct avs_dev *adev, struct avs_mods_info **info)
 	return 0;
 }
 
+int avs_ipc_set_enable_logs(struct avs_dev *adev, u8 *log_info, size_t size)
+{
+	int ret;
+
+	ret = avs_ipc_set_large_config(adev, AVS_BASEFW_MOD_ID, AVS_BASEFW_INST_ID,
+				       AVS_BASEFW_ENABLE_LOGS, log_info, size);
+	if (ret)
+		dev_err(adev->dev, "enable logs failed: %d\n", ret);
+
+	return ret;
+}
+
+int avs_ipc_set_system_time(struct avs_dev *adev)
+{
+	struct avs_sys_time sys_time;
+	int ret;
+	u64 us;
+
+	/* firmware expects UTC time in micro seconds */
+	us = ktime_to_us(ktime_get());
+	sys_time.val_l = us & UINT_MAX;
+	sys_time.val_u = us >> 32;
+
+	ret = avs_ipc_set_large_config(adev, AVS_BASEFW_MOD_ID, AVS_BASEFW_INST_ID,
+				       AVS_BASEFW_SYSTEM_TIME, (u8 *)&sys_time, sizeof(sys_time));
+	if (ret)
+		dev_err(adev->dev, "set system time failed: %d\n", ret);
+
+	return ret;
+}
+
 int avs_ipc_copier_set_sink_format(struct avs_dev *adev, u16 module_id,
 				   u8 instance_id, u32 sink_id,
 				   const struct avs_audio_format *src_fmt,
diff --git a/sound/soc/intel/avs/messages.h b/sound/soc/intel/avs/messages.h
index 94875a153124..257482e160bc 100644
--- a/sound/soc/intel/avs/messages.h
+++ b/sound/soc/intel/avs/messages.h
@@ -186,6 +186,7 @@ union avs_reply_msg {
 enum avs_notify_msg_type {
 	AVS_NOTIFY_PHRASE_DETECTED = 4,
 	AVS_NOTIFY_RESOURCE_EVENT = 5,
+	AVS_NOTIFY_LOG_BUFFER_STATUS = 6,
 	AVS_NOTIFY_FW_READY = 8,
 	AVS_NOTIFY_EXCEPTION_CAUGHT = 10,
 	AVS_NOTIFY_MODULE_EVENT = 12,
@@ -203,6 +204,10 @@ union avs_notify_msg {
 				u32 msg_direction:1;
 				u32 msg_target:1;
 			};
+			struct {
+				u16 rsvd:12;
+				u16 core:4;
+			} log;
 		};
 		union {
 			u32 val;
@@ -329,12 +334,21 @@ int avs_ipc_set_d0ix(struct avs_dev *adev, bool enable_pg, bool streaming);
 #define AVS_BASEFW_INST_ID	0
 
 enum avs_basefw_runtime_param {
+	AVS_BASEFW_ENABLE_LOGS = 6,
 	AVS_BASEFW_FIRMWARE_CONFIG = 7,
 	AVS_BASEFW_HARDWARE_CONFIG = 8,
 	AVS_BASEFW_MODULES_INFO = 9,
 	AVS_BASEFW_LIBRARIES_INFO = 16,
+	AVS_BASEFW_SYSTEM_TIME = 20,
+};
+
+enum avs_log_enable {
+	AVS_LOG_DISABLE = 0,
+	AVS_LOG_ENABLE = 1
 };
 
+int avs_ipc_set_enable_logs(struct avs_dev *adev, u8 *log_info, size_t size);
+
 struct avs_fw_version {
 	u16 major;
 	u16 minor;
@@ -502,6 +516,13 @@ static inline bool avs_module_entry_is_loaded(struct avs_module_entry *mentry)
 
 int avs_ipc_get_modules_info(struct avs_dev *adev, struct avs_mods_info **info);
 
+struct avs_sys_time {
+	u32 val_l;
+	u32 val_u;
+} __packed;
+
+int avs_ipc_set_system_time(struct avs_dev *adev);
+
 /* Module configuration */
 
 #define AVS_MIXIN_MOD_UUID \
diff --git a/sound/soc/intel/avs/registers.h b/sound/soc/intel/avs/registers.h
index 3fd02389ed2b..f951d3441cdf 100644
--- a/sound/soc/intel/avs/registers.h
+++ b/sound/soc/intel/avs/registers.h
@@ -58,6 +58,7 @@
 #define AVS_UPLINK_WINDOW		AVS_FW_REGS_WINDOW
 /* HOST -> DSP communication window */
 #define AVS_DOWNLINK_WINDOW		1
+#define AVS_DEBUG_WINDOW		2
 
 /* registry I/O helpers */
 #define avs_sram_offset(adev, window_idx) \
diff --git a/sound/soc/intel/avs/utils.c b/sound/soc/intel/avs/utils.c
index 6473e3ae4c6e..13611dee9787 100644
--- a/sound/soc/intel/avs/utils.c
+++ b/sound/soc/intel/avs/utils.c
@@ -7,6 +7,7 @@
 //
 
 #include <linux/firmware.h>
+#include <linux/kfifo.h>
 #include <linux/slab.h>
 #include "avs.h"
 #include "messages.h"
@@ -299,3 +300,25 @@ void avs_release_firmwares(struct avs_dev *adev)
 		kfree(entry);
 	}
 }
+
+unsigned int __kfifo_fromio_locked(struct kfifo *fifo, const void __iomem *src, unsigned int len,
+				   spinlock_t *lock)
+{
+	struct __kfifo *__fifo = &fifo->kfifo;
+	unsigned long flags;
+	unsigned int l, off;
+
+	spin_lock_irqsave(lock, flags);
+	len = min(len, kfifo_avail(fifo));
+	off = __fifo->in & __fifo->mask;
+	l = min(len, kfifo_size(fifo) - off);
+
+	memcpy_fromio(__fifo->data + off, src, l);
+	memcpy_fromio(__fifo->data, src + l, len - l);
+	/* Make sure data copied from SRAM is visible to all CPUs. */
+	smp_mb();
+	__fifo->in += len;
+	spin_unlock_irqrestore(lock, flags);
+
+	return len;
+}
