loader.c (ed32f8d42cee118b075e4372a55c7739a11094b2) loader.c (83ee7ab1627b7597bbb9acc26b37e9f96fff40c9)
1// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
2//
3// This file is provided under a dual BSD/GPLv2 license. When using or
4// redistributing this file, you may do so under either license.
5//
6// Copyright(c) 2018 Intel Corporation. All rights reserved.
7//
8// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>

--- 73 unchanged lines hidden (view full) ---

82 ext_hdr = ext_data;
83 }
84
85 kfree(ext_data);
86 return ret;
87}
88EXPORT_SYMBOL(snd_sof_fw_parse_ext_data);
89
1// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
2//
3// This file is provided under a dual BSD/GPLv2 license. When using or
4// redistributing this file, you may do so under either license.
5//
6// Copyright(c) 2018 Intel Corporation. All rights reserved.
7//
8// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>

--- 73 unchanged lines hidden (view full) ---

82 ext_hdr = ext_data;
83 }
84
85 kfree(ext_data);
86 return ret;
87}
88EXPORT_SYMBOL(snd_sof_fw_parse_ext_data);
89
90/*
91 * IPC Firmware ready.
92 */
93static void sof_get_windows(struct snd_sof_dev *sdev)
94{
95 struct sof_ipc_window_elem *elem;
96 u32 outbox_offset = 0;
97 u32 stream_offset = 0;
98 u32 inbox_offset = 0;
99 u32 outbox_size = 0;
100 u32 stream_size = 0;
101 u32 inbox_size = 0;
102 int window_offset;
103 int bar;
104 int i;
105
106 if (!sdev->info_window) {
107 dev_err(sdev->dev, "error: have no window info\n");
108 return;
109 }
110
111 bar = snd_sof_dsp_get_bar_index(sdev, SOF_FW_BLK_TYPE_SRAM);
112 if (bar < 0) {
113 dev_err(sdev->dev, "error: have no bar mapping\n");
114 return;
115 }
116
117 for (i = 0; i < sdev->info_window->num_windows; i++) {
118 elem = &sdev->info_window->window[i];
119
120 window_offset = snd_sof_dsp_get_window_offset(sdev, elem->id);
121 if (window_offset < 0) {
122 dev_warn(sdev->dev, "warn: no offset for window %d\n",
123 elem->id);
124 continue;
125 }
126
127 switch (elem->type) {
128 case SOF_IPC_REGION_UPBOX:
129 inbox_offset = window_offset + elem->offset;
130 inbox_size = elem->size;
131 snd_sof_debugfs_io_item(sdev,
132 sdev->bar[bar] +
133 inbox_offset,
134 elem->size, "inbox",
135 SOF_DEBUGFS_ACCESS_D0_ONLY);
136 break;
137 case SOF_IPC_REGION_DOWNBOX:
138 outbox_offset = window_offset + elem->offset;
139 outbox_size = elem->size;
140 snd_sof_debugfs_io_item(sdev,
141 sdev->bar[bar] +
142 outbox_offset,
143 elem->size, "outbox",
144 SOF_DEBUGFS_ACCESS_D0_ONLY);
145 break;
146 case SOF_IPC_REGION_TRACE:
147 snd_sof_debugfs_io_item(sdev,
148 sdev->bar[bar] +
149 window_offset +
150 elem->offset,
151 elem->size, "etrace",
152 SOF_DEBUGFS_ACCESS_D0_ONLY);
153 break;
154 case SOF_IPC_REGION_DEBUG:
155 snd_sof_debugfs_io_item(sdev,
156 sdev->bar[bar] +
157 window_offset +
158 elem->offset,
159 elem->size, "debug",
160 SOF_DEBUGFS_ACCESS_D0_ONLY);
161 break;
162 case SOF_IPC_REGION_STREAM:
163 stream_offset = window_offset + elem->offset;
164 stream_size = elem->size;
165 snd_sof_debugfs_io_item(sdev,
166 sdev->bar[bar] +
167 stream_offset,
168 elem->size, "stream",
169 SOF_DEBUGFS_ACCESS_D0_ONLY);
170 break;
171 case SOF_IPC_REGION_REGS:
172 snd_sof_debugfs_io_item(sdev,
173 sdev->bar[bar] +
174 window_offset +
175 elem->offset,
176 elem->size, "regs",
177 SOF_DEBUGFS_ACCESS_D0_ONLY);
178 break;
179 case SOF_IPC_REGION_EXCEPTION:
180 sdev->dsp_oops_offset = window_offset + elem->offset;
181 snd_sof_debugfs_io_item(sdev,
182 sdev->bar[bar] +
183 window_offset +
184 elem->offset,
185 elem->size, "exception",
186 SOF_DEBUGFS_ACCESS_D0_ONLY);
187 break;
188 default:
189 dev_err(sdev->dev, "error: get illegal window info\n");
190 return;
191 }
192 }
193
194 if (outbox_size == 0 || inbox_size == 0) {
195 dev_err(sdev->dev, "error: get illegal mailbox window\n");
196 return;
197 }
198
199 snd_sof_dsp_mailbox_init(sdev, inbox_offset, inbox_size,
200 outbox_offset, outbox_size);
201 sdev->stream_box.offset = stream_offset;
202 sdev->stream_box.size = stream_size;
203
204 dev_dbg(sdev->dev, " mailbox upstream 0x%x - size 0x%x\n",
205 inbox_offset, inbox_size);
206 dev_dbg(sdev->dev, " mailbox downstream 0x%x - size 0x%x\n",
207 outbox_offset, outbox_size);
208 dev_dbg(sdev->dev, " stream region 0x%x - size 0x%x\n",
209 stream_offset, stream_size);
210}
211
212/* check for ABI compatibility and create memory windows on first boot */
213int sof_fw_ready(struct snd_sof_dev *sdev, u32 msg_id)
214{
215 struct sof_ipc_fw_ready *fw_ready = &sdev->fw_ready;
216 int offset;
217 int bar;
218 int ret;
219
220 /* mailbox must be on 4k boundary */
221 offset = snd_sof_dsp_get_mailbox_offset(sdev);
222 if (offset < 0) {
223 dev_err(sdev->dev, "error: have no mailbox offset\n");
224 return offset;
225 }
226
227 bar = snd_sof_dsp_get_bar_index(sdev, SOF_FW_BLK_TYPE_SRAM);
228 if (bar < 0) {
229 dev_err(sdev->dev, "error: have no bar mapping\n");
230 return -EINVAL;
231 }
232
233 dev_dbg(sdev->dev, "ipc: DSP is ready 0x%8.8x offset 0x%x\n",
234 msg_id, offset);
235
236 /* no need to re-check version/ABI for subsequent boots */
237 if (!sdev->first_boot)
238 return 0;
239
240 /* copy data from the DSP FW ready offset */
241 sof_block_read(sdev, bar, offset, fw_ready, sizeof(*fw_ready));
242
243 /* make sure ABI version is compatible */
244 ret = snd_sof_ipc_valid(sdev);
245 if (ret < 0)
246 return ret;
247
248 /* now check for extended data */
249 snd_sof_fw_parse_ext_data(sdev, bar, offset +
250 sizeof(struct sof_ipc_fw_ready));
251
252 sof_get_windows(sdev);
253
254 return 0;
255}
256EXPORT_SYMBOL(sof_fw_ready);
257
90/* generic module parser for mmaped DSPs */
91int snd_sof_parse_module_memcpy(struct snd_sof_dev *sdev,
92 struct snd_sof_mod_hdr *module)
93{
94 struct snd_sof_blk_hdr *block;
258/* generic module parser for mmaped DSPs */
259int snd_sof_parse_module_memcpy(struct snd_sof_dev *sdev,
260 struct snd_sof_mod_hdr *module)
261{
262 struct snd_sof_blk_hdr *block;
95 int count;
263 int count, bar;
96 u32 offset;
97 size_t remaining;
98
99 dev_dbg(sdev->dev, "new module size 0x%x blocks 0x%x type 0x%x\n",
100 module->size, module->num_blocks, module->type);
101
102 block = (struct snd_sof_blk_hdr *)((u8 *)module + sizeof(*module));
103

--- 14 unchanged lines hidden (view full) ---

118 "warning: block %d size zero\n", count);
119 dev_warn(sdev->dev, " type 0x%x offset 0x%x\n",
120 block->type, block->offset);
121 continue;
122 }
123
124 switch (block->type) {
125 case SOF_FW_BLK_TYPE_RSRVD0:
264 u32 offset;
265 size_t remaining;
266
267 dev_dbg(sdev->dev, "new module size 0x%x blocks 0x%x type 0x%x\n",
268 module->size, module->num_blocks, module->type);
269
270 block = (struct snd_sof_blk_hdr *)((u8 *)module + sizeof(*module));
271

--- 14 unchanged lines hidden (view full) ---

286 "warning: block %d size zero\n", count);
287 dev_warn(sdev->dev, " type 0x%x offset 0x%x\n",
288 block->type, block->offset);
289 continue;
290 }
291
292 switch (block->type) {
293 case SOF_FW_BLK_TYPE_RSRVD0:
126 case SOF_FW_BLK_TYPE_SRAM...SOF_FW_BLK_TYPE_RSRVD14:
294 case SOF_FW_BLK_TYPE_ROM...SOF_FW_BLK_TYPE_RSRVD14:
127 continue; /* not handled atm */
128 case SOF_FW_BLK_TYPE_IRAM:
129 case SOF_FW_BLK_TYPE_DRAM:
295 continue; /* not handled atm */
296 case SOF_FW_BLK_TYPE_IRAM:
297 case SOF_FW_BLK_TYPE_DRAM:
298 case SOF_FW_BLK_TYPE_SRAM:
130 offset = block->offset;
299 offset = block->offset;
300 bar = snd_sof_dsp_get_bar_index(sdev, block->type);
301 if (bar < 0) {
302 dev_err(sdev->dev,
303 "error: no BAR mapping for block type 0x%x\n",
304 block->type);
305 return bar;
306 }
131 break;
132 default:
133 dev_err(sdev->dev, "error: bad type 0x%x for block 0x%x\n",
134 block->type, count);
135 return -EINVAL;
136 }
137
138 dev_dbg(sdev->dev,
139 "block %d type 0x%x size 0x%x ==> offset 0x%x\n",
140 count, block->type, block->size, offset);
141
142 /* checking block->size to avoid unaligned access */
143 if (block->size % sizeof(u32)) {
144 dev_err(sdev->dev, "error: invalid block size 0x%x\n",
145 block->size);
146 return -EINVAL;
147 }
307 break;
308 default:
309 dev_err(sdev->dev, "error: bad type 0x%x for block 0x%x\n",
310 block->type, count);
311 return -EINVAL;
312 }
313
314 dev_dbg(sdev->dev,
315 "block %d type 0x%x size 0x%x ==> offset 0x%x\n",
316 count, block->type, block->size, offset);
317
318 /* checking block->size to avoid unaligned access */
319 if (block->size % sizeof(u32)) {
320 dev_err(sdev->dev, "error: invalid block size 0x%x\n",
321 block->size);
322 return -EINVAL;
323 }
148 snd_sof_dsp_block_write(sdev, sdev->mmio_bar, offset,
324 snd_sof_dsp_block_write(sdev, bar, offset,
149 block + 1, block->size);
150
151 if (remaining < block->size) {
152 dev_err(sdev->dev, "error: not enough data remaining\n");
153 return -EINVAL;
154 }
155
156 /* minus body size of block */

--- 244 unchanged lines hidden ---
325 block + 1, block->size);
326
327 if (remaining < block->size) {
328 dev_err(sdev->dev, "error: not enough data remaining\n");
329 return -EINVAL;
330 }
331
332 /* minus body size of block */

--- 244 unchanged lines hidden ---