16
16
#include "../sof-audio.h"
17
17
#include "acp.h"
18
18
#include "acp-dsp-offset.h"
19
+ #include <sound/sof/xtensa.h>
19
20
20
21
int acp_dai_probe (struct snd_soc_dai * dai )
21
22
{
@@ -33,6 +34,107 @@ int acp_dai_probe(struct snd_soc_dai *dai)
33
34
}
34
35
EXPORT_SYMBOL_NS (acp_dai_probe , SND_SOC_SOF_AMD_COMMON );
35
36
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
+
36
138
struct snd_soc_acpi_mach * amd_sof_machine_select (struct snd_sof_dev * sdev )
37
139
{
38
140
struct snd_sof_pdata * sof_pdata = sdev -> pdata ;
@@ -104,9 +206,15 @@ struct snd_sof_dsp_ops sof_acp_common_ops = {
104
206
/* PM */
105
207
.suspend = amd_sof_acp_suspend ,
106
208
.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 ,
107
214
};
108
215
EXPORT_SYMBOL_NS (sof_acp_common_ops , SND_SOC_SOF_AMD_COMMON );
109
216
110
217
MODULE_IMPORT_NS (SND_SOC_SOF_AMD_COMMON );
218
+ MODULE_IMPORT_NS (SND_SOC_SOF_XTENSA );
111
219
MODULE_DESCRIPTION ("ACP SOF COMMON Driver" );
112
220
MODULE_LICENSE ("Dual BSD/GPL" );
0 commit comments