1616#include "../sof-audio.h"
1717#include "acp.h"
1818#include "acp-dsp-offset.h"
19+ #include <sound/sof/xtensa.h>
1920
2021int acp_dai_probe (struct snd_soc_dai * dai )
2122{
@@ -33,6 +34,107 @@ int acp_dai_probe(struct snd_soc_dai *dai)
3334}
3435EXPORT_SYMBOL_NS (acp_dai_probe , SND_SOC_SOF_AMD_COMMON );
3536
37+ /**
38+ * amd_sof_ipc_dump() - This function is called when IPC tx times out.
39+ * @sdev: SOF device.
40+ */
41+ void amd_sof_ipc_dump (struct snd_sof_dev * sdev )
42+ {
43+ const struct sof_amd_acp_desc * desc = get_chip_info (sdev -> pdata );
44+ u32 base = desc -> dsp_intr_base ;
45+ u32 dsp_msg_write = sdev -> debug_box .offset +
46+ offsetof(struct scratch_ipc_conf , sof_dsp_msg_write );
47+ u32 dsp_ack_write = sdev -> debug_box .offset +
48+ offsetof(struct scratch_ipc_conf , sof_dsp_ack_write );
49+ u32 host_msg_write = sdev -> debug_box .offset +
50+ offsetof(struct scratch_ipc_conf , sof_host_msg_write );
51+ u32 host_ack_write = sdev -> debug_box .offset +
52+ offsetof(struct scratch_ipc_conf , sof_host_ack_write );
53+ u32 dsp_msg , dsp_ack , host_msg , host_ack , irq_stat ;
54+
55+ dsp_msg = snd_sof_dsp_read (sdev , ACP_DSP_BAR , ACP_SCRATCH_REG_0 + dsp_msg_write );
56+ dsp_ack = snd_sof_dsp_read (sdev , ACP_DSP_BAR , ACP_SCRATCH_REG_0 + dsp_ack_write );
57+ host_msg = snd_sof_dsp_read (sdev , ACP_DSP_BAR , ACP_SCRATCH_REG_0 + host_msg_write );
58+ host_ack = snd_sof_dsp_read (sdev , ACP_DSP_BAR , ACP_SCRATCH_REG_0 + host_ack_write );
59+ irq_stat = snd_sof_dsp_read (sdev , ACP_DSP_BAR , base + DSP_SW_INTR_STAT_OFFSET );
60+
61+ dev_err (sdev -> dev ,
62+ "dsp_msg = %#x dsp_ack = %#x host_msg = %#x host_ack = %#x irq_stat = %#x\n" ,
63+ dsp_msg , dsp_ack , host_msg , host_ack , irq_stat );
64+ }
65+
66+ /**
67+ * amd_get_registers() - This function is called in case of DSP oops
68+ * in order to gather information about the registers, filename and
69+ * linenumber and stack.
70+ * @sdev: SOF device.
71+ * @xoops: Stores information about registers.
72+ * @panic_info: Stores information about filename and line number.
73+ * @stack: Stores the stack dump.
74+ * @stack_words: Size of the stack dump.
75+ */
76+ static void amd_get_registers (struct snd_sof_dev * sdev ,
77+ struct sof_ipc_dsp_oops_xtensa * xoops ,
78+ struct sof_ipc_panic_info * panic_info ,
79+ u32 * stack , size_t stack_words )
80+ {
81+ u32 offset = sdev -> dsp_oops_offset ;
82+
83+ /* first read registers */
84+ acp_mailbox_read (sdev , offset , xoops , sizeof (* xoops ));
85+
86+ /* then get panic info */
87+ if (xoops -> arch_hdr .totalsize > EXCEPT_MAX_HDR_SIZE ) {
88+ dev_err (sdev -> dev , "invalid header size 0x%x. FW oops is bogus\n" ,
89+ xoops -> arch_hdr .totalsize );
90+ return ;
91+ }
92+
93+ offset += xoops -> arch_hdr .totalsize ;
94+ acp_mailbox_read (sdev , offset , panic_info , sizeof (* panic_info ));
95+
96+ /* then get the stack */
97+ offset += sizeof (* panic_info );
98+ acp_mailbox_read (sdev , offset , stack , stack_words * sizeof (u32 ));
99+ }
100+
101+ /**
102+ * amd_sof_dump() - This function is called when a panic message is
103+ * received from the firmware.
104+ * @sdev: SOF device.
105+ * @flags: parameter not used but required by ops prototype
106+ */
107+ void amd_sof_dump (struct snd_sof_dev * sdev , u32 flags )
108+ {
109+ struct sof_ipc_dsp_oops_xtensa xoops ;
110+ struct sof_ipc_panic_info panic_info ;
111+ u32 stack [AMD_STACK_DUMP_SIZE ];
112+ u32 status ;
113+
114+ /* Get information about the panic status from the debug box area.
115+ * Compute the trace point based on the status.
116+ */
117+ if (sdev -> dsp_oops_offset > sdev -> debug_box .offset ) {
118+ acp_mailbox_read (sdev , sdev -> debug_box .offset , & status , sizeof (u32 ));
119+ } else {
120+ /* Read DSP Panic status from dsp_box.
121+ * As window information for exception box offset and size is not available
122+ * before FW_READY
123+ */
124+ acp_mailbox_read (sdev , sdev -> dsp_box .offset , & status , sizeof (u32 ));
125+ sdev -> dsp_oops_offset = sdev -> dsp_box .offset + sizeof (status );
126+ }
127+
128+ /* Get information about the registers, the filename and line
129+ * number and the stack.
130+ */
131+ amd_get_registers (sdev , & xoops , & panic_info , stack , AMD_STACK_DUMP_SIZE );
132+
133+ /* Print the information to the console */
134+ sof_print_oops_and_stack (sdev , KERN_ERR , status , status , & xoops ,
135+ & panic_info , stack , AMD_STACK_DUMP_SIZE );
136+ }
137+
36138struct snd_soc_acpi_mach * amd_sof_machine_select (struct snd_sof_dev * sdev )
37139{
38140 struct snd_sof_pdata * sof_pdata = sdev -> pdata ;
@@ -104,9 +206,15 @@ struct snd_sof_dsp_ops sof_acp_common_ops = {
104206 /* PM */
105207 .suspend = amd_sof_acp_suspend ,
106208 .resume = amd_sof_acp_resume ,
209+
210+ .ipc_dump = amd_sof_ipc_dump ,
211+ .dbg_dump = amd_sof_dump ,
212+ .debugfs_add_region_item = snd_sof_debugfs_add_region_item_iomem ,
213+ .dsp_arch_ops = & sof_xtensa_arch_ops ,
107214};
108215EXPORT_SYMBOL_NS (sof_acp_common_ops , SND_SOC_SOF_AMD_COMMON );
109216
110217MODULE_IMPORT_NS (SND_SOC_SOF_AMD_COMMON );
218+ MODULE_IMPORT_NS (SND_SOC_SOF_XTENSA );
111219MODULE_DESCRIPTION ("ACP SOF COMMON Driver" );
112220MODULE_LICENSE ("Dual BSD/GPL" );
0 commit comments