18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
28c2ecf20Sopenharmony_ci//
38c2ecf20Sopenharmony_ci// Copyright 2020 NXP
48c2ecf20Sopenharmony_ci//
58c2ecf20Sopenharmony_ci// Common helpers for the audio DSP on i.MX8
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#include <linux/module.h>
88c2ecf20Sopenharmony_ci#include <sound/sof/xtensa.h>
98c2ecf20Sopenharmony_ci#include "../ops.h"
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#include "imx-common.h"
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci/**
148c2ecf20Sopenharmony_ci * imx8_get_registers() - This function is called in case of DSP oops
158c2ecf20Sopenharmony_ci * in order to gather information about the registers, filename and
168c2ecf20Sopenharmony_ci * linenumber and stack.
178c2ecf20Sopenharmony_ci * @sdev: SOF device
188c2ecf20Sopenharmony_ci * @xoops: Stores information about registers.
198c2ecf20Sopenharmony_ci * @panic_info: Stores information about filename and line number.
208c2ecf20Sopenharmony_ci * @stack: Stores the stack dump.
218c2ecf20Sopenharmony_ci * @stack_words: Size of the stack dump.
228c2ecf20Sopenharmony_ci */
238c2ecf20Sopenharmony_civoid imx8_get_registers(struct snd_sof_dev *sdev,
248c2ecf20Sopenharmony_ci			struct sof_ipc_dsp_oops_xtensa *xoops,
258c2ecf20Sopenharmony_ci			struct sof_ipc_panic_info *panic_info,
268c2ecf20Sopenharmony_ci			u32 *stack, size_t stack_words)
278c2ecf20Sopenharmony_ci{
288c2ecf20Sopenharmony_ci	u32 offset = sdev->dsp_oops_offset;
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci	/* first read registers */
318c2ecf20Sopenharmony_ci	sof_mailbox_read(sdev, offset, xoops, sizeof(*xoops));
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci	/* then get panic info */
348c2ecf20Sopenharmony_ci	if (xoops->arch_hdr.totalsize > EXCEPT_MAX_HDR_SIZE) {
358c2ecf20Sopenharmony_ci		dev_err(sdev->dev, "invalid header size 0x%x. FW oops is bogus\n",
368c2ecf20Sopenharmony_ci			xoops->arch_hdr.totalsize);
378c2ecf20Sopenharmony_ci		return;
388c2ecf20Sopenharmony_ci	}
398c2ecf20Sopenharmony_ci	offset += xoops->arch_hdr.totalsize;
408c2ecf20Sopenharmony_ci	sof_mailbox_read(sdev, offset, panic_info, sizeof(*panic_info));
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci	/* then get the stack */
438c2ecf20Sopenharmony_ci	offset += sizeof(*panic_info);
448c2ecf20Sopenharmony_ci	sof_mailbox_read(sdev, offset, stack, stack_words * sizeof(u32));
458c2ecf20Sopenharmony_ci}
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci/**
488c2ecf20Sopenharmony_ci * imx8_dump() - This function is called when a panic message is
498c2ecf20Sopenharmony_ci * received from the firmware.
508c2ecf20Sopenharmony_ci */
518c2ecf20Sopenharmony_civoid imx8_dump(struct snd_sof_dev *sdev, u32 flags)
528c2ecf20Sopenharmony_ci{
538c2ecf20Sopenharmony_ci	struct sof_ipc_dsp_oops_xtensa xoops;
548c2ecf20Sopenharmony_ci	struct sof_ipc_panic_info panic_info;
558c2ecf20Sopenharmony_ci	u32 stack[IMX8_STACK_DUMP_SIZE];
568c2ecf20Sopenharmony_ci	u32 status;
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci	/* Get information about the panic status from the debug box area.
598c2ecf20Sopenharmony_ci	 * Compute the trace point based on the status.
608c2ecf20Sopenharmony_ci	 */
618c2ecf20Sopenharmony_ci	sof_mailbox_read(sdev, sdev->debug_box.offset + 0x4, &status, 4);
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ci	/* Get information about the registers, the filename and line
648c2ecf20Sopenharmony_ci	 * number and the stack.
658c2ecf20Sopenharmony_ci	 */
668c2ecf20Sopenharmony_ci	imx8_get_registers(sdev, &xoops, &panic_info, stack,
678c2ecf20Sopenharmony_ci			   IMX8_STACK_DUMP_SIZE);
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci	/* Print the information to the console */
708c2ecf20Sopenharmony_ci	snd_sof_get_status(sdev, status, status, &xoops, &panic_info, stack,
718c2ecf20Sopenharmony_ci			   IMX8_STACK_DUMP_SIZE);
728c2ecf20Sopenharmony_ci}
738c2ecf20Sopenharmony_ciEXPORT_SYMBOL(imx8_dump);
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ciMODULE_LICENSE("Dual BSD/GPL");
76