xref: /linux/drivers/firmware/cirrus/cs_dsp.c (revision 9e3d4f794cbe9a4e286b3052cb97908005807aee)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * cs_dsp.c  --  Cirrus Logic DSP firmware support
4  *
5  * Based on sound/soc/codecs/wm_adsp.c
6  *
7  * Copyright 2012 Wolfson Microelectronics plc
8  * Copyright (C) 2015-2021 Cirrus Logic, Inc. and
9  *                         Cirrus Logic International Semiconductor Ltd.
10  */
11 
12 #include <linux/cleanup.h>
13 #include <linux/ctype.h>
14 #include <linux/debugfs.h>
15 #include <linux/delay.h>
16 #include <linux/math.h>
17 #include <linux/minmax.h>
18 #include <linux/module.h>
19 #include <linux/moduleparam.h>
20 #include <linux/seq_file.h>
21 #include <linux/slab.h>
22 #include <linux/vmalloc.h>
23 
24 #include <linux/firmware/cirrus/cs_dsp.h>
25 #include <linux/firmware/cirrus/wmfw.h>
26 
27 #define cs_dsp_err(_dsp, fmt, ...) \
28 	dev_err(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__)
29 #define cs_dsp_warn(_dsp, fmt, ...) \
30 	dev_warn(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__)
31 #define cs_dsp_info(_dsp, fmt, ...) \
32 	dev_info(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__)
33 #define cs_dsp_dbg(_dsp, fmt, ...) \
34 	dev_dbg(_dsp->dev, "%s: " fmt, _dsp->name, ##__VA_ARGS__)
35 
36 #define ADSP1_CONTROL_1                   0x00
37 #define ADSP1_CONTROL_2                   0x02
38 #define ADSP1_CONTROL_3                   0x03
39 #define ADSP1_CONTROL_4                   0x04
40 #define ADSP1_CONTROL_5                   0x06
41 #define ADSP1_CONTROL_6                   0x07
42 #define ADSP1_CONTROL_7                   0x08
43 #define ADSP1_CONTROL_8                   0x09
44 #define ADSP1_CONTROL_9                   0x0A
45 #define ADSP1_CONTROL_10                  0x0B
46 #define ADSP1_CONTROL_11                  0x0C
47 #define ADSP1_CONTROL_12                  0x0D
48 #define ADSP1_CONTROL_13                  0x0F
49 #define ADSP1_CONTROL_14                  0x10
50 #define ADSP1_CONTROL_15                  0x11
51 #define ADSP1_CONTROL_16                  0x12
52 #define ADSP1_CONTROL_17                  0x13
53 #define ADSP1_CONTROL_18                  0x14
54 #define ADSP1_CONTROL_19                  0x16
55 #define ADSP1_CONTROL_20                  0x17
56 #define ADSP1_CONTROL_21                  0x18
57 #define ADSP1_CONTROL_22                  0x1A
58 #define ADSP1_CONTROL_23                  0x1B
59 #define ADSP1_CONTROL_24                  0x1C
60 #define ADSP1_CONTROL_25                  0x1E
61 #define ADSP1_CONTROL_26                  0x20
62 #define ADSP1_CONTROL_27                  0x21
63 #define ADSP1_CONTROL_28                  0x22
64 #define ADSP1_CONTROL_29                  0x23
65 #define ADSP1_CONTROL_30                  0x24
66 #define ADSP1_CONTROL_31                  0x26
67 
68 /*
69  * ADSP1 Control 19
70  */
71 #define ADSP1_WDMA_BUFFER_LENGTH_MASK     0x00FF  /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
72 #define ADSP1_WDMA_BUFFER_LENGTH_SHIFT         0  /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
73 #define ADSP1_WDMA_BUFFER_LENGTH_WIDTH         8  /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
74 
75 /*
76  * ADSP1 Control 30
77  */
78 #define ADSP1_DBG_CLK_ENA                 0x0008  /* DSP1_DBG_CLK_ENA */
79 #define ADSP1_DBG_CLK_ENA_MASK            0x0008  /* DSP1_DBG_CLK_ENA */
80 #define ADSP1_DBG_CLK_ENA_SHIFT                3  /* DSP1_DBG_CLK_ENA */
81 #define ADSP1_DBG_CLK_ENA_WIDTH                1  /* DSP1_DBG_CLK_ENA */
82 #define ADSP1_SYS_ENA                     0x0004  /* DSP1_SYS_ENA */
83 #define ADSP1_SYS_ENA_MASK                0x0004  /* DSP1_SYS_ENA */
84 #define ADSP1_SYS_ENA_SHIFT                    2  /* DSP1_SYS_ENA */
85 #define ADSP1_SYS_ENA_WIDTH                    1  /* DSP1_SYS_ENA */
86 #define ADSP1_CORE_ENA                    0x0002  /* DSP1_CORE_ENA */
87 #define ADSP1_CORE_ENA_MASK               0x0002  /* DSP1_CORE_ENA */
88 #define ADSP1_CORE_ENA_SHIFT                   1  /* DSP1_CORE_ENA */
89 #define ADSP1_CORE_ENA_WIDTH                   1  /* DSP1_CORE_ENA */
90 #define ADSP1_START                       0x0001  /* DSP1_START */
91 #define ADSP1_START_MASK                  0x0001  /* DSP1_START */
92 #define ADSP1_START_SHIFT                      0  /* DSP1_START */
93 #define ADSP1_START_WIDTH                      1  /* DSP1_START */
94 
95 /*
96  * ADSP1 Control 31
97  */
98 #define ADSP1_CLK_SEL_MASK                0x0007  /* CLK_SEL_ENA */
99 #define ADSP1_CLK_SEL_SHIFT                    0  /* CLK_SEL_ENA */
100 #define ADSP1_CLK_SEL_WIDTH                    3  /* CLK_SEL_ENA */
101 
102 #define ADSP2_CONTROL                     0x0
103 #define ADSP2_CLOCKING                    0x1
104 #define ADSP2V2_CLOCKING                  0x2
105 #define ADSP2_STATUS1                     0x4
106 #define ADSP2_WDMA_CONFIG_1               0x30
107 #define ADSP2_WDMA_CONFIG_2               0x31
108 #define ADSP2V2_WDMA_CONFIG_2             0x32
109 #define ADSP2_RDMA_CONFIG_1               0x34
110 
111 #define ADSP2_SCRATCH0                    0x40
112 #define ADSP2_SCRATCH1                    0x41
113 #define ADSP2_SCRATCH2                    0x42
114 #define ADSP2_SCRATCH3                    0x43
115 
116 #define ADSP2V2_SCRATCH0_1                0x40
117 #define ADSP2V2_SCRATCH2_3                0x42
118 
119 /*
120  * ADSP2 Control
121  */
122 #define ADSP2_MEM_ENA                     0x0010  /* DSP1_MEM_ENA */
123 #define ADSP2_MEM_ENA_MASK                0x0010  /* DSP1_MEM_ENA */
124 #define ADSP2_MEM_ENA_SHIFT                    4  /* DSP1_MEM_ENA */
125 #define ADSP2_MEM_ENA_WIDTH                    1  /* DSP1_MEM_ENA */
126 #define ADSP2_SYS_ENA                     0x0004  /* DSP1_SYS_ENA */
127 #define ADSP2_SYS_ENA_MASK                0x0004  /* DSP1_SYS_ENA */
128 #define ADSP2_SYS_ENA_SHIFT                    2  /* DSP1_SYS_ENA */
129 #define ADSP2_SYS_ENA_WIDTH                    1  /* DSP1_SYS_ENA */
130 #define ADSP2_CORE_ENA                    0x0002  /* DSP1_CORE_ENA */
131 #define ADSP2_CORE_ENA_MASK               0x0002  /* DSP1_CORE_ENA */
132 #define ADSP2_CORE_ENA_SHIFT                   1  /* DSP1_CORE_ENA */
133 #define ADSP2_CORE_ENA_WIDTH                   1  /* DSP1_CORE_ENA */
134 #define ADSP2_START                       0x0001  /* DSP1_START */
135 #define ADSP2_START_MASK                  0x0001  /* DSP1_START */
136 #define ADSP2_START_SHIFT                      0  /* DSP1_START */
137 #define ADSP2_START_WIDTH                      1  /* DSP1_START */
138 
139 /*
140  * ADSP2 clocking
141  */
142 #define ADSP2_CLK_SEL_MASK                0x0007  /* CLK_SEL_ENA */
143 #define ADSP2_CLK_SEL_SHIFT                    0  /* CLK_SEL_ENA */
144 #define ADSP2_CLK_SEL_WIDTH                    3  /* CLK_SEL_ENA */
145 
146 /*
147  * ADSP2V2 clocking
148  */
149 #define ADSP2V2_CLK_SEL_MASK             0x70000  /* CLK_SEL_ENA */
150 #define ADSP2V2_CLK_SEL_SHIFT                 16  /* CLK_SEL_ENA */
151 #define ADSP2V2_CLK_SEL_WIDTH                  3  /* CLK_SEL_ENA */
152 
153 #define ADSP2V2_RATE_MASK                 0x7800  /* DSP_RATE */
154 #define ADSP2V2_RATE_SHIFT                    11  /* DSP_RATE */
155 #define ADSP2V2_RATE_WIDTH                     4  /* DSP_RATE */
156 
157 /*
158  * ADSP2 Status 1
159  */
160 #define ADSP2_RAM_RDY                     0x0001
161 #define ADSP2_RAM_RDY_MASK                0x0001
162 #define ADSP2_RAM_RDY_SHIFT                    0
163 #define ADSP2_RAM_RDY_WIDTH                    1
164 
165 /*
166  * ADSP2 Lock support
167  */
168 #define ADSP2_LOCK_CODE_0                    0x5555
169 #define ADSP2_LOCK_CODE_1                    0xAAAA
170 
171 #define ADSP2_WATCHDOG                       0x0A
172 #define ADSP2_BUS_ERR_ADDR                   0x52
173 #define ADSP2_REGION_LOCK_STATUS             0x64
174 #define ADSP2_LOCK_REGION_1_LOCK_REGION_0    0x66
175 #define ADSP2_LOCK_REGION_3_LOCK_REGION_2    0x68
176 #define ADSP2_LOCK_REGION_5_LOCK_REGION_4    0x6A
177 #define ADSP2_LOCK_REGION_7_LOCK_REGION_6    0x6C
178 #define ADSP2_LOCK_REGION_9_LOCK_REGION_8    0x6E
179 #define ADSP2_LOCK_REGION_CTRL               0x7A
180 #define ADSP2_PMEM_ERR_ADDR_XMEM_ERR_ADDR    0x7C
181 
182 #define ADSP2_REGION_LOCK_ERR_MASK           0x8000
183 #define ADSP2_ADDR_ERR_MASK                  0x4000
184 #define ADSP2_WDT_TIMEOUT_STS_MASK           0x2000
185 #define ADSP2_CTRL_ERR_PAUSE_ENA             0x0002
186 #define ADSP2_CTRL_ERR_EINT                  0x0001
187 
188 #define ADSP2_BUS_ERR_ADDR_MASK              0x00FFFFFF
189 #define ADSP2_XMEM_ERR_ADDR_MASK             0x0000FFFF
190 #define ADSP2_PMEM_ERR_ADDR_MASK             0x7FFF0000
191 #define ADSP2_PMEM_ERR_ADDR_SHIFT            16
192 #define ADSP2_WDT_ENA_MASK                   0xFFFFFFFD
193 
194 #define ADSP2_LOCK_REGION_SHIFT              16
195 
196 /*
197  * Event control messages
198  */
199 #define CS_DSP_FW_EVENT_SHUTDOWN             0x000001
200 
201 /*
202  * HALO system info
203  */
204 #define HALO_AHBM_WINDOW_DEBUG_0             0x02040
205 #define HALO_AHBM_WINDOW_DEBUG_1             0x02044
206 
207 /*
208  * HALO core
209  */
210 #define HALO_SCRATCH1                        0x005c0
211 #define HALO_SCRATCH2                        0x005c8
212 #define HALO_SCRATCH3                        0x005d0
213 #define HALO_SCRATCH4                        0x005d8
214 #define HALO_CCM_CORE_CONTROL                0x41000
215 #define HALO_CORE_SOFT_RESET                 0x00010
216 #define HALO_WDT_CONTROL                     0x47000
217 
218 /*
219  * HALO MPU banks
220  */
221 #define HALO_MPU_XMEM_ACCESS_0               0x43000
222 #define HALO_MPU_YMEM_ACCESS_0               0x43004
223 #define HALO_MPU_WINDOW_ACCESS_0             0x43008
224 #define HALO_MPU_XREG_ACCESS_0               0x4300C
225 #define HALO_MPU_YREG_ACCESS_0               0x43014
226 #define HALO_MPU_XMEM_ACCESS_1               0x43018
227 #define HALO_MPU_YMEM_ACCESS_1               0x4301C
228 #define HALO_MPU_WINDOW_ACCESS_1             0x43020
229 #define HALO_MPU_XREG_ACCESS_1               0x43024
230 #define HALO_MPU_YREG_ACCESS_1               0x4302C
231 #define HALO_MPU_XMEM_ACCESS_2               0x43030
232 #define HALO_MPU_YMEM_ACCESS_2               0x43034
233 #define HALO_MPU_WINDOW_ACCESS_2             0x43038
234 #define HALO_MPU_XREG_ACCESS_2               0x4303C
235 #define HALO_MPU_YREG_ACCESS_2               0x43044
236 #define HALO_MPU_XMEM_ACCESS_3               0x43048
237 #define HALO_MPU_YMEM_ACCESS_3               0x4304C
238 #define HALO_MPU_WINDOW_ACCESS_3             0x43050
239 #define HALO_MPU_XREG_ACCESS_3               0x43054
240 #define HALO_MPU_YREG_ACCESS_3               0x4305C
241 #define HALO_MPU_XM_VIO_ADDR                 0x43100
242 #define HALO_MPU_XM_VIO_STATUS               0x43104
243 #define HALO_MPU_YM_VIO_ADDR                 0x43108
244 #define HALO_MPU_YM_VIO_STATUS               0x4310C
245 #define HALO_MPU_PM_VIO_ADDR                 0x43110
246 #define HALO_MPU_PM_VIO_STATUS               0x43114
247 #define HALO_MPU_LOCK_CONFIG                 0x43140
248 
249 /*
250  * HALO_AHBM_WINDOW_DEBUG_1
251  */
252 #define HALO_AHBM_CORE_ERR_ADDR_MASK         0x0fffff00
253 #define HALO_AHBM_CORE_ERR_ADDR_SHIFT                 8
254 #define HALO_AHBM_FLAGS_ERR_MASK             0x000000ff
255 
256 /*
257  * HALO_CCM_CORE_CONTROL
258  */
259 #define HALO_CORE_RESET                     0x00000200
260 #define HALO_CORE_EN                        0x00000001
261 
262 /*
263  * HALO_CORE_SOFT_RESET
264  */
265 #define HALO_CORE_SOFT_RESET_MASK           0x00000001
266 
267 /*
268  * HALO_WDT_CONTROL
269  */
270 #define HALO_WDT_EN_MASK                    0x00000001
271 
272 /*
273  * HALO_MPU_?M_VIO_STATUS
274  */
275 #define HALO_MPU_VIO_STS_MASK               0x007e0000
276 #define HALO_MPU_VIO_STS_SHIFT                      17
277 #define HALO_MPU_VIO_ERR_WR_MASK            0x00008000
278 #define HALO_MPU_VIO_ERR_SRC_MASK           0x00007fff
279 #define HALO_MPU_VIO_ERR_SRC_SHIFT                   0
280 
281 /*
282  * Write Sequence
283  */
284 #define WSEQ_OP_MAX_WORDS	3
285 #define WSEQ_END_OF_SCRIPT	0xFFFFFF
286 
287 struct cs_dsp_ops {
288 	bool (*validate_version)(struct cs_dsp *dsp, unsigned int version);
289 	unsigned int (*parse_sizes)(struct cs_dsp *dsp,
290 				    const char * const file,
291 				    unsigned int pos,
292 				    const struct firmware *firmware);
293 	int (*setup_algs)(struct cs_dsp *dsp);
294 	unsigned int (*region_to_reg)(struct cs_dsp_region const *mem,
295 				      unsigned int offset);
296 
297 	void (*show_fw_status)(struct cs_dsp *dsp);
298 	void (*stop_watchdog)(struct cs_dsp *dsp);
299 
300 	int (*enable_memory)(struct cs_dsp *dsp);
301 	void (*disable_memory)(struct cs_dsp *dsp);
302 	int (*lock_memory)(struct cs_dsp *dsp, unsigned int lock_regions);
303 
304 	int (*enable_core)(struct cs_dsp *dsp);
305 	void (*disable_core)(struct cs_dsp *dsp);
306 
307 	int (*start_core)(struct cs_dsp *dsp);
308 	void (*stop_core)(struct cs_dsp *dsp);
309 };
310 
311 static const struct cs_dsp_ops cs_dsp_adsp1_ops;
312 static const struct cs_dsp_ops cs_dsp_adsp2_ops[];
313 static const struct cs_dsp_ops cs_dsp_halo_ops;
314 static const struct cs_dsp_ops cs_dsp_halo_ao_ops;
315 
316 struct cs_dsp_alg_region_list_item {
317 	struct list_head list;
318 	struct cs_dsp_alg_region alg_region;
319 };
320 
321 /**
322  * cs_dsp_mem_region_name() - Return a name string for a memory type
323  * @type: the memory type to match
324  *
325  * Return: A const string identifying the memory region.
326  */
327 const char *cs_dsp_mem_region_name(unsigned int type)
328 {
329 	switch (type) {
330 	case WMFW_ADSP1_PM:
331 		return "PM";
332 	case WMFW_HALO_PM_PACKED:
333 		return "PM_PACKED";
334 	case WMFW_ADSP1_DM:
335 		return "DM";
336 	case WMFW_ADSP2_XM:
337 		return "XM";
338 	case WMFW_HALO_XM_PACKED:
339 		return "XM_PACKED";
340 	case WMFW_ADSP2_YM:
341 		return "YM";
342 	case WMFW_HALO_YM_PACKED:
343 		return "YM_PACKED";
344 	case WMFW_ADSP1_ZM:
345 		return "ZM";
346 	default:
347 		return NULL;
348 	}
349 }
350 EXPORT_SYMBOL_NS_GPL(cs_dsp_mem_region_name, "FW_CS_DSP");
351 
352 #ifdef CONFIG_DEBUG_FS
353 static void cs_dsp_debugfs_save_wmfwname(struct cs_dsp *dsp, const char *s)
354 {
355 	kfree(dsp->wmfw_file_name);
356 	dsp->wmfw_file_name = kstrdup(s, GFP_KERNEL);
357 }
358 
359 static void cs_dsp_debugfs_save_binname(struct cs_dsp *dsp, const char *s)
360 {
361 	kfree(dsp->bin_file_name);
362 	dsp->bin_file_name = kstrdup(s, GFP_KERNEL);
363 }
364 
365 static void cs_dsp_debugfs_clear(struct cs_dsp *dsp)
366 {
367 	kfree(dsp->wmfw_file_name);
368 	kfree(dsp->bin_file_name);
369 	dsp->wmfw_file_name = NULL;
370 	dsp->bin_file_name = NULL;
371 }
372 
373 static ssize_t cs_dsp_debugfs_string_read(struct cs_dsp *dsp,
374 					  char __user *user_buf,
375 					  size_t count, loff_t *ppos,
376 					  const char **pstr)
377 {
378 	const char *str;
379 	ssize_t ret = 0;
380 
381 	scoped_guard(mutex, &dsp->pwr_lock) {
382 		if (*pstr) {
383 			str = kasprintf(GFP_KERNEL, "%s\n", *pstr);
384 			if (str) {
385 				ret = simple_read_from_buffer(user_buf, count,
386 							      ppos, str, strlen(str));
387 				kfree(str);
388 			} else {
389 				ret = -ENOMEM;
390 			}
391 		}
392 	}
393 
394 	return ret;
395 }
396 
397 static ssize_t cs_dsp_debugfs_wmfw_read(struct file *file,
398 					char __user *user_buf,
399 					size_t count, loff_t *ppos)
400 {
401 	struct cs_dsp *dsp = file->private_data;
402 
403 	return cs_dsp_debugfs_string_read(dsp, user_buf, count, ppos,
404 					  &dsp->wmfw_file_name);
405 }
406 
407 static ssize_t cs_dsp_debugfs_bin_read(struct file *file,
408 				       char __user *user_buf,
409 				       size_t count, loff_t *ppos)
410 {
411 	struct cs_dsp *dsp = file->private_data;
412 
413 	return cs_dsp_debugfs_string_read(dsp, user_buf, count, ppos,
414 					  &dsp->bin_file_name);
415 }
416 
417 static const struct {
418 	const char *name;
419 	const struct file_operations fops;
420 } cs_dsp_debugfs_fops[] = {
421 	{
422 		.name = "wmfw_file_name",
423 		.fops = {
424 			.open = simple_open,
425 			.read = cs_dsp_debugfs_wmfw_read,
426 		},
427 	},
428 	{
429 		.name = "bin_file_name",
430 		.fops = {
431 			.open = simple_open,
432 			.read = cs_dsp_debugfs_bin_read,
433 		},
434 	},
435 };
436 
437 static int cs_dsp_coeff_base_reg(struct cs_dsp_coeff_ctl *ctl, unsigned int *reg,
438 				 unsigned int off);
439 
440 static int cs_dsp_debugfs_read_controls_show(struct seq_file *s, void *ignored)
441 {
442 	struct cs_dsp *dsp = s->private;
443 	struct cs_dsp_coeff_ctl *ctl;
444 	unsigned int reg;
445 
446 	guard(mutex)(&dsp->pwr_lock);
447 
448 	list_for_each_entry(ctl, &dsp->ctl_list, list) {
449 		cs_dsp_coeff_base_reg(ctl, &reg, 0);
450 		seq_printf(s, "%22.*s: %#8x %s:%08x %#8x %s %#8x %#4x %c%c%c%c %s %s\n",
451 			   ctl->subname_len, ctl->subname, ctl->len,
452 			   cs_dsp_mem_region_name(ctl->alg_region.type),
453 			   ctl->offset, reg, ctl->fw_name, ctl->alg_region.alg, ctl->type,
454 			   ctl->flags & WMFW_CTL_FLAG_VOLATILE ? 'V' : '-',
455 			   ctl->flags & WMFW_CTL_FLAG_SYS ? 'S' : '-',
456 			   ctl->flags & WMFW_CTL_FLAG_READABLE ? 'R' : '-',
457 			   ctl->flags & WMFW_CTL_FLAG_WRITEABLE ? 'W' : '-',
458 			   ctl->enabled ? "enabled" : "disabled",
459 			   ctl->set ? "dirty" : "clean");
460 	}
461 
462 	return 0;
463 }
464 DEFINE_SHOW_ATTRIBUTE(cs_dsp_debugfs_read_controls);
465 
466 /**
467  * cs_dsp_init_debugfs() - Create and populate DSP representation in debugfs
468  * @dsp: pointer to DSP structure
469  * @debugfs_root: pointer to debugfs directory in which to create this DSP
470  *                representation
471  */
472 void cs_dsp_init_debugfs(struct cs_dsp *dsp, struct dentry *debugfs_root)
473 {
474 	struct dentry *root = NULL;
475 	int i;
476 
477 	root = debugfs_create_dir(dsp->name, debugfs_root);
478 
479 	debugfs_create_bool("booted", 0444, root, &dsp->booted);
480 	debugfs_create_bool("running", 0444, root, &dsp->running);
481 	debugfs_create_x32("fw_id", 0444, root, &dsp->fw_id);
482 	debugfs_create_x32("fw_version", 0444, root, &dsp->fw_id_version);
483 
484 	for (i = 0; i < ARRAY_SIZE(cs_dsp_debugfs_fops); ++i)
485 		debugfs_create_file(cs_dsp_debugfs_fops[i].name, 0444, root,
486 				    dsp, &cs_dsp_debugfs_fops[i].fops);
487 
488 	debugfs_create_file("controls", 0444, root, dsp,
489 			    &cs_dsp_debugfs_read_controls_fops);
490 
491 	dsp->debugfs_root = root;
492 }
493 EXPORT_SYMBOL_NS_GPL(cs_dsp_init_debugfs, "FW_CS_DSP");
494 
495 /**
496  * cs_dsp_cleanup_debugfs() - Removes DSP representation from debugfs
497  * @dsp: pointer to DSP structure
498  */
499 void cs_dsp_cleanup_debugfs(struct cs_dsp *dsp)
500 {
501 	cs_dsp_debugfs_clear(dsp);
502 	debugfs_remove_recursive(dsp->debugfs_root);
503 	dsp->debugfs_root = ERR_PTR(-ENODEV);
504 }
505 EXPORT_SYMBOL_NS_GPL(cs_dsp_cleanup_debugfs, "FW_CS_DSP");
506 #else
507 void cs_dsp_init_debugfs(struct cs_dsp *dsp, struct dentry *debugfs_root)
508 {
509 }
510 EXPORT_SYMBOL_NS_GPL(cs_dsp_init_debugfs, "FW_CS_DSP");
511 
512 void cs_dsp_cleanup_debugfs(struct cs_dsp *dsp)
513 {
514 }
515 EXPORT_SYMBOL_NS_GPL(cs_dsp_cleanup_debugfs, "FW_CS_DSP");
516 
517 static inline void cs_dsp_debugfs_save_wmfwname(struct cs_dsp *dsp,
518 						const char *s)
519 {
520 }
521 
522 static inline void cs_dsp_debugfs_save_binname(struct cs_dsp *dsp,
523 					       const char *s)
524 {
525 }
526 
527 static inline void cs_dsp_debugfs_clear(struct cs_dsp *dsp)
528 {
529 }
530 #endif
531 
532 static const struct cs_dsp_region *cs_dsp_find_region(struct cs_dsp *dsp,
533 						      int type)
534 {
535 	int i;
536 
537 	for (i = 0; i < dsp->num_mems; i++)
538 		if (dsp->mem[i].type == type)
539 			return &dsp->mem[i];
540 
541 	return NULL;
542 }
543 
544 static unsigned int cs_dsp_region_to_reg(struct cs_dsp_region const *mem,
545 					 unsigned int offset)
546 {
547 	switch (mem->type) {
548 	case WMFW_ADSP1_PM:
549 		return mem->base + (offset * 3);
550 	case WMFW_ADSP1_DM:
551 	case WMFW_ADSP2_XM:
552 	case WMFW_ADSP2_YM:
553 	case WMFW_ADSP1_ZM:
554 		return mem->base + (offset * 2);
555 	default:
556 		WARN(1, "Unknown memory region type");
557 		return offset;
558 	}
559 }
560 
561 static unsigned int cs_dsp_halo_region_to_reg(struct cs_dsp_region const *mem,
562 					      unsigned int offset)
563 {
564 	switch (mem->type) {
565 	case WMFW_ADSP2_XM:
566 	case WMFW_ADSP2_YM:
567 		return mem->base + (offset * 4);
568 	case WMFW_HALO_XM_PACKED:
569 	case WMFW_HALO_YM_PACKED:
570 		return (mem->base + (offset * 3)) & ~0x3;
571 	case WMFW_HALO_PM_PACKED:
572 		return mem->base + (offset * 5);
573 	default:
574 		WARN(1, "Unknown memory region type");
575 		return offset;
576 	}
577 }
578 
579 static void cs_dsp_read_fw_status(struct cs_dsp *dsp,
580 				  int noffs, unsigned int *offs)
581 {
582 	unsigned int i;
583 	int ret;
584 
585 	for (i = 0; i < noffs; ++i) {
586 		ret = regmap_read(dsp->regmap, dsp->base + offs[i], &offs[i]);
587 		if (ret) {
588 			cs_dsp_err(dsp, "Failed to read SCRATCH%u: %d\n", i, ret);
589 			return;
590 		}
591 	}
592 }
593 
594 static void cs_dsp_adsp2_show_fw_status(struct cs_dsp *dsp)
595 {
596 	unsigned int offs[] = {
597 		ADSP2_SCRATCH0, ADSP2_SCRATCH1, ADSP2_SCRATCH2, ADSP2_SCRATCH3,
598 	};
599 
600 	cs_dsp_read_fw_status(dsp, ARRAY_SIZE(offs), offs);
601 
602 	cs_dsp_dbg(dsp, "FW SCRATCH 0:0x%x 1:0x%x 2:0x%x 3:0x%x\n",
603 		   offs[0], offs[1], offs[2], offs[3]);
604 }
605 
606 static void cs_dsp_adsp2v2_show_fw_status(struct cs_dsp *dsp)
607 {
608 	unsigned int offs[] = { ADSP2V2_SCRATCH0_1, ADSP2V2_SCRATCH2_3 };
609 
610 	cs_dsp_read_fw_status(dsp, ARRAY_SIZE(offs), offs);
611 
612 	cs_dsp_dbg(dsp, "FW SCRATCH 0:0x%x 1:0x%x 2:0x%x 3:0x%x\n",
613 		   offs[0] & 0xFFFF, offs[0] >> 16,
614 		   offs[1] & 0xFFFF, offs[1] >> 16);
615 }
616 
617 static void cs_dsp_halo_show_fw_status(struct cs_dsp *dsp)
618 {
619 	unsigned int offs[] = {
620 		HALO_SCRATCH1, HALO_SCRATCH2, HALO_SCRATCH3, HALO_SCRATCH4,
621 	};
622 
623 	cs_dsp_read_fw_status(dsp, ARRAY_SIZE(offs), offs);
624 
625 	cs_dsp_dbg(dsp, "FW SCRATCH 0:0x%x 1:0x%x 2:0x%x 3:0x%x\n",
626 		   offs[0], offs[1], offs[2], offs[3]);
627 }
628 
629 static int cs_dsp_coeff_base_reg(struct cs_dsp_coeff_ctl *ctl, unsigned int *reg,
630 				 unsigned int off)
631 {
632 	const struct cs_dsp_alg_region *alg_region = &ctl->alg_region;
633 	struct cs_dsp *dsp = ctl->dsp;
634 	const struct cs_dsp_region *mem;
635 
636 	mem = cs_dsp_find_region(dsp, alg_region->type);
637 	if (!mem) {
638 		cs_dsp_err(dsp, "No base for region %x\n",
639 			   alg_region->type);
640 		return -EINVAL;
641 	}
642 
643 	*reg = dsp->ops->region_to_reg(mem, ctl->alg_region.base + ctl->offset + off);
644 
645 	return 0;
646 }
647 
648 /**
649  * cs_dsp_coeff_write_acked_control() - Sends event_id to the acked control
650  * @ctl: pointer to acked coefficient control
651  * @event_id: the value to write to the given acked control
652  *
653  * Once the value has been written to the control the function shall block
654  * until the running firmware acknowledges the write or timeout is exceeded.
655  *
656  * Must be called with pwr_lock held.
657  *
658  * Return: Zero for success, a negative number on error.
659  */
660 int cs_dsp_coeff_write_acked_control(struct cs_dsp_coeff_ctl *ctl, unsigned int event_id)
661 {
662 	struct cs_dsp *dsp = ctl->dsp;
663 	__be32 val = cpu_to_be32(event_id);
664 	unsigned int reg;
665 	int i, ret;
666 
667 	lockdep_assert_held(&dsp->pwr_lock);
668 
669 	if (!dsp->running)
670 		return -EPERM;
671 
672 	ret = cs_dsp_coeff_base_reg(ctl, &reg, 0);
673 	if (ret)
674 		return ret;
675 
676 	cs_dsp_dbg(dsp, "Sending 0x%x to acked control alg 0x%x %s:0x%x\n",
677 		   event_id, ctl->alg_region.alg,
678 		   cs_dsp_mem_region_name(ctl->alg_region.type), ctl->offset);
679 
680 	ret = regmap_raw_write(dsp->regmap, reg, &val, sizeof(val));
681 	if (ret) {
682 		cs_dsp_err(dsp, "Failed to write %x: %d\n", reg, ret);
683 		return ret;
684 	}
685 
686 	/*
687 	 * Poll for ack, we initially poll at ~1ms intervals for firmwares
688 	 * that respond quickly, then go to ~10ms polls. A firmware is unlikely
689 	 * to ack instantly so we do the first 1ms delay before reading the
690 	 * control to avoid a pointless bus transaction
691 	 */
692 	for (i = 0; i < CS_DSP_ACKED_CTL_TIMEOUT_MS;) {
693 		switch (i) {
694 		case 0 ... CS_DSP_ACKED_CTL_N_QUICKPOLLS - 1:
695 			usleep_range(1000, 2000);
696 			i++;
697 			break;
698 		default:
699 			usleep_range(10000, 20000);
700 			i += 10;
701 			break;
702 		}
703 
704 		ret = regmap_raw_read(dsp->regmap, reg, &val, sizeof(val));
705 		if (ret) {
706 			cs_dsp_err(dsp, "Failed to read %x: %d\n", reg, ret);
707 			return ret;
708 		}
709 
710 		if (val == 0) {
711 			cs_dsp_dbg(dsp, "Acked control ACKED at poll %u\n", i);
712 			return 0;
713 		}
714 	}
715 
716 	cs_dsp_warn(dsp, "Acked control @0x%x alg:0x%x %s:0x%x timed out\n",
717 		    reg, ctl->alg_region.alg,
718 		    cs_dsp_mem_region_name(ctl->alg_region.type),
719 		    ctl->offset);
720 
721 	return -ETIMEDOUT;
722 }
723 EXPORT_SYMBOL_NS_GPL(cs_dsp_coeff_write_acked_control, "FW_CS_DSP");
724 
725 static int cs_dsp_coeff_write_ctrl_raw(struct cs_dsp_coeff_ctl *ctl,
726 				       unsigned int off, const void *buf, size_t len)
727 {
728 	struct cs_dsp *dsp = ctl->dsp;
729 	void *scratch;
730 	int ret;
731 	unsigned int reg;
732 
733 	ret = cs_dsp_coeff_base_reg(ctl, &reg, off);
734 	if (ret)
735 		return ret;
736 
737 	scratch = kmemdup(buf, len, GFP_KERNEL | GFP_DMA);
738 	if (!scratch)
739 		return -ENOMEM;
740 
741 	ret = regmap_raw_write(dsp->regmap, reg, scratch,
742 			       len);
743 	if (ret) {
744 		cs_dsp_err(dsp, "Failed to write %zu bytes to %x: %d\n",
745 			   len, reg, ret);
746 		kfree(scratch);
747 		return ret;
748 	}
749 	cs_dsp_dbg(dsp, "Wrote %zu bytes to %x\n", len, reg);
750 
751 	kfree(scratch);
752 
753 	return 0;
754 }
755 
756 /**
757  * cs_dsp_coeff_write_ctrl() - Writes the given buffer to the given coefficient control
758  * @ctl: pointer to coefficient control
759  * @off: word offset at which data should be written
760  * @buf: the buffer to write to the given control
761  * @len: the length of the buffer in bytes
762  *
763  * Must be called with pwr_lock held.
764  *
765  * Return: < 0 on error, 1 when the control value changed and 0 when it has not.
766  */
767 int cs_dsp_coeff_write_ctrl(struct cs_dsp_coeff_ctl *ctl,
768 			    unsigned int off, const void *buf, size_t len)
769 {
770 	int ret = 0;
771 
772 	if (!ctl)
773 		return -ENOENT;
774 
775 	lockdep_assert_held(&ctl->dsp->pwr_lock);
776 
777 	if (ctl->flags && !(ctl->flags & WMFW_CTL_FLAG_WRITEABLE))
778 		return -EPERM;
779 
780 	if (len + off * sizeof(u32) > ctl->len)
781 		return -EINVAL;
782 
783 	if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) {
784 		ret = -EPERM;
785 	} else if (buf != ctl->cache) {
786 		if (memcmp(ctl->cache + off * sizeof(u32), buf, len))
787 			memcpy(ctl->cache + off * sizeof(u32), buf, len);
788 		else
789 			return 0;
790 	}
791 
792 	ctl->set = 1;
793 	if (ctl->enabled && ctl->dsp->running)
794 		ret = cs_dsp_coeff_write_ctrl_raw(ctl, off, buf, len);
795 
796 	if (ret < 0)
797 		return ret;
798 
799 	return 1;
800 }
801 EXPORT_SYMBOL_NS_GPL(cs_dsp_coeff_write_ctrl, "FW_CS_DSP");
802 
803 /**
804  * cs_dsp_coeff_lock_and_write_ctrl() - Writes the given buffer to the given coefficient control
805  * @ctl: pointer to coefficient control
806  * @off: word offset at which data should be written
807  * @buf: the buffer to write to the given control
808  * @len: the length of the buffer in bytes
809  *
810  * Same as cs_dsp_coeff_write_ctrl() but takes pwr_lock.
811  *
812  * Return: A negative number on error, 1 when the control value changed and 0 when it has not.
813  */
814 int cs_dsp_coeff_lock_and_write_ctrl(struct cs_dsp_coeff_ctl *ctl,
815 				     unsigned int off, const void *buf, size_t len)
816 {
817 	struct cs_dsp *dsp = ctl->dsp;
818 	int ret;
819 
820 	lockdep_assert_not_held(&dsp->pwr_lock);
821 
822 	mutex_lock(&dsp->pwr_lock);
823 	ret = cs_dsp_coeff_write_ctrl(ctl, off, buf, len);
824 	mutex_unlock(&dsp->pwr_lock);
825 
826 	return ret;
827 }
828 EXPORT_SYMBOL_GPL(cs_dsp_coeff_lock_and_write_ctrl);
829 
830 static int cs_dsp_coeff_read_ctrl_raw(struct cs_dsp_coeff_ctl *ctl,
831 				      unsigned int off, void *buf, size_t len)
832 {
833 	struct cs_dsp *dsp = ctl->dsp;
834 	void *scratch;
835 	int ret;
836 	unsigned int reg;
837 
838 	ret = cs_dsp_coeff_base_reg(ctl, &reg, off);
839 	if (ret)
840 		return ret;
841 
842 	scratch = kmalloc(len, GFP_KERNEL | GFP_DMA);
843 	if (!scratch)
844 		return -ENOMEM;
845 
846 	ret = regmap_raw_read(dsp->regmap, reg, scratch, len);
847 	if (ret) {
848 		cs_dsp_err(dsp, "Failed to read %zu bytes from %x: %d\n",
849 			   len, reg, ret);
850 		kfree(scratch);
851 		return ret;
852 	}
853 	cs_dsp_dbg(dsp, "Read %zu bytes from %x\n", len, reg);
854 
855 	memcpy(buf, scratch, len);
856 	kfree(scratch);
857 
858 	return 0;
859 }
860 
861 /**
862  * cs_dsp_coeff_read_ctrl() - Reads the given coefficient control into the given buffer
863  * @ctl: pointer to coefficient control
864  * @off: word offset at which data should be read
865  * @buf: the buffer to store to the given control
866  * @len: the length of the buffer in bytes
867  *
868  * Must be called with pwr_lock held.
869  *
870  * Return: Zero for success, a negative number on error.
871  */
872 int cs_dsp_coeff_read_ctrl(struct cs_dsp_coeff_ctl *ctl,
873 			   unsigned int off, void *buf, size_t len)
874 {
875 	int ret = 0;
876 
877 	if (!ctl)
878 		return -ENOENT;
879 
880 	lockdep_assert_held(&ctl->dsp->pwr_lock);
881 
882 	if (len + off * sizeof(u32) > ctl->len)
883 		return -EINVAL;
884 
885 	if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) {
886 		if (ctl->enabled && ctl->dsp->running)
887 			return cs_dsp_coeff_read_ctrl_raw(ctl, off, buf, len);
888 		else
889 			return -EPERM;
890 	} else {
891 		if (!ctl->flags && ctl->enabled && ctl->dsp->running)
892 			ret = cs_dsp_coeff_read_ctrl_raw(ctl, 0, ctl->cache, ctl->len);
893 
894 		if (buf != ctl->cache)
895 			memcpy(buf, ctl->cache + off * sizeof(u32), len);
896 	}
897 
898 	return ret;
899 }
900 EXPORT_SYMBOL_NS_GPL(cs_dsp_coeff_read_ctrl, "FW_CS_DSP");
901 
902 /**
903  * cs_dsp_coeff_lock_and_read_ctrl() - Reads the given coefficient control into the given buffer
904  * @ctl: pointer to coefficient control
905  * @off: word offset at which data should be read
906  * @buf: the buffer to store to the given control
907  * @len: the length of the buffer in bytes
908  *
909  * Same as cs_dsp_coeff_read_ctrl() but takes pwr_lock.
910  *
911  * Return: Zero for success, a negative number on error.
912  */
913 int cs_dsp_coeff_lock_and_read_ctrl(struct cs_dsp_coeff_ctl *ctl,
914 				    unsigned int off, void *buf, size_t len)
915 {
916 	struct cs_dsp *dsp = ctl->dsp;
917 	int ret;
918 
919 	lockdep_assert_not_held(&dsp->pwr_lock);
920 
921 	mutex_lock(&dsp->pwr_lock);
922 	ret = cs_dsp_coeff_read_ctrl(ctl, off, buf, len);
923 	mutex_unlock(&dsp->pwr_lock);
924 
925 	return ret;
926 }
927 EXPORT_SYMBOL_GPL(cs_dsp_coeff_lock_and_read_ctrl);
928 
929 static int cs_dsp_coeff_init_control_caches(struct cs_dsp *dsp)
930 {
931 	struct cs_dsp_coeff_ctl *ctl;
932 	int ret;
933 
934 	list_for_each_entry(ctl, &dsp->ctl_list, list) {
935 		if (!ctl->enabled || ctl->set)
936 			continue;
937 		if (ctl->flags & WMFW_CTL_FLAG_VOLATILE)
938 			continue;
939 
940 		/*
941 		 * For readable controls populate the cache from the DSP memory.
942 		 * For non-readable controls the cache was zero-filled when
943 		 * created so we don't need to do anything.
944 		 */
945 		if (!ctl->flags || (ctl->flags & WMFW_CTL_FLAG_READABLE)) {
946 			ret = cs_dsp_coeff_read_ctrl_raw(ctl, 0, ctl->cache, ctl->len);
947 			if (ret < 0)
948 				return ret;
949 		}
950 	}
951 
952 	return 0;
953 }
954 
955 static int cs_dsp_coeff_sync_controls(struct cs_dsp *dsp)
956 {
957 	struct cs_dsp_coeff_ctl *ctl;
958 	int ret;
959 
960 	list_for_each_entry(ctl, &dsp->ctl_list, list) {
961 		if (!ctl->enabled)
962 			continue;
963 		if (ctl->set && !(ctl->flags & WMFW_CTL_FLAG_VOLATILE)) {
964 			ret = cs_dsp_coeff_write_ctrl_raw(ctl, 0, ctl->cache,
965 							  ctl->len);
966 			if (ret < 0)
967 				return ret;
968 		}
969 	}
970 
971 	return 0;
972 }
973 
974 static void cs_dsp_signal_event_controls(struct cs_dsp *dsp,
975 					 unsigned int event)
976 {
977 	struct cs_dsp_coeff_ctl *ctl;
978 	int ret;
979 
980 	list_for_each_entry(ctl, &dsp->ctl_list, list) {
981 		if (ctl->type != WMFW_CTL_TYPE_HOSTEVENT)
982 			continue;
983 
984 		if (!ctl->enabled)
985 			continue;
986 
987 		ret = cs_dsp_coeff_write_acked_control(ctl, event);
988 		if (ret)
989 			cs_dsp_warn(dsp,
990 				    "Failed to send 0x%x event to alg 0x%x (%d)\n",
991 				    event, ctl->alg_region.alg, ret);
992 	}
993 }
994 
995 static void cs_dsp_free_ctl_blk(struct cs_dsp_coeff_ctl *ctl)
996 {
997 	kvfree(ctl->cache);
998 	kfree(ctl->subname);
999 	kfree(ctl);
1000 }
1001 
1002 static int cs_dsp_create_control(struct cs_dsp *dsp,
1003 				 const struct cs_dsp_alg_region *alg_region,
1004 				 unsigned int offset, unsigned int len,
1005 				 const char *subname, unsigned int subname_len,
1006 				 unsigned int flags, unsigned int type)
1007 {
1008 	struct cs_dsp_coeff_ctl *ctl;
1009 	int ret;
1010 
1011 	list_for_each_entry(ctl, &dsp->ctl_list, list) {
1012 		if (ctl->fw_name == dsp->fw_name &&
1013 		    ctl->alg_region.alg == alg_region->alg &&
1014 		    ctl->alg_region.type == alg_region->type) {
1015 			if ((!subname && !ctl->subname) ||
1016 			    (subname && (ctl->subname_len == subname_len) &&
1017 			     !strncmp(ctl->subname, subname, ctl->subname_len))) {
1018 				if (!ctl->enabled)
1019 					ctl->enabled = 1;
1020 				return 0;
1021 			}
1022 		}
1023 	}
1024 
1025 	ctl = kzalloc(sizeof(*ctl), GFP_KERNEL);
1026 	if (!ctl)
1027 		return -ENOMEM;
1028 
1029 	ctl->fw_name = dsp->fw_name;
1030 	ctl->alg_region = *alg_region;
1031 	if (subname && dsp->wmfw_ver >= 2) {
1032 		ctl->subname_len = subname_len;
1033 		ctl->subname = kasprintf(GFP_KERNEL, "%.*s", subname_len, subname);
1034 		if (!ctl->subname) {
1035 			ret = -ENOMEM;
1036 			goto err_ctl;
1037 		}
1038 	}
1039 	ctl->enabled = 1;
1040 	ctl->set = 0;
1041 	ctl->dsp = dsp;
1042 
1043 	ctl->flags = flags;
1044 	ctl->type = type;
1045 	ctl->offset = offset;
1046 	ctl->len = len;
1047 	ctl->cache = kvzalloc(ctl->len, GFP_KERNEL);
1048 	if (!ctl->cache) {
1049 		ret = -ENOMEM;
1050 		goto err_ctl_subname;
1051 	}
1052 
1053 	list_add(&ctl->list, &dsp->ctl_list);
1054 
1055 	if (dsp->client_ops->control_add) {
1056 		ret = dsp->client_ops->control_add(ctl);
1057 		if (ret)
1058 			goto err_list_del;
1059 	}
1060 
1061 	return 0;
1062 
1063 err_list_del:
1064 	list_del(&ctl->list);
1065 	kvfree(ctl->cache);
1066 err_ctl_subname:
1067 	kfree(ctl->subname);
1068 err_ctl:
1069 	kfree(ctl);
1070 
1071 	return ret;
1072 }
1073 
1074 struct cs_dsp_coeff_parsed_alg {
1075 	int id;
1076 	const u8 *name;
1077 	int name_len;
1078 	int ncoeff;
1079 };
1080 
1081 struct cs_dsp_coeff_parsed_coeff {
1082 	int offset;
1083 	int mem_type;
1084 	const u8 *name;
1085 	int name_len;
1086 	unsigned int ctl_type;
1087 	int flags;
1088 	int len;
1089 };
1090 
1091 static int cs_dsp_coeff_parse_string(int bytes, const u8 **pos, unsigned int avail,
1092 				     const u8 **str)
1093 {
1094 	int length, total_field_len;
1095 
1096 	/* String fields are at least one __le32 */
1097 	if (sizeof(__le32) > avail) {
1098 		*pos = NULL;
1099 		return 0;
1100 	}
1101 
1102 	switch (bytes) {
1103 	case 1:
1104 		length = **pos;
1105 		break;
1106 	case 2:
1107 		length = le16_to_cpu(*((__le16 *)*pos));
1108 		break;
1109 	default:
1110 		return 0;
1111 	}
1112 
1113 	total_field_len = ((length + bytes) + 3) & ~0x03;
1114 	if ((unsigned int)total_field_len > avail) {
1115 		*pos = NULL;
1116 		return 0;
1117 	}
1118 
1119 	if (str)
1120 		*str = *pos + bytes;
1121 
1122 	*pos += total_field_len;
1123 
1124 	return length;
1125 }
1126 
1127 static int cs_dsp_coeff_parse_int(int bytes, const u8 **pos)
1128 {
1129 	int val = 0;
1130 
1131 	switch (bytes) {
1132 	case 2:
1133 		val = le16_to_cpu(*((__le16 *)*pos));
1134 		break;
1135 	case 4:
1136 		val = le32_to_cpu(*((__le32 *)*pos));
1137 		break;
1138 	default:
1139 		break;
1140 	}
1141 
1142 	*pos += bytes;
1143 
1144 	return val;
1145 }
1146 
1147 static int cs_dsp_coeff_parse_alg(struct cs_dsp *dsp,
1148 				  const struct wmfw_region *region,
1149 				  struct cs_dsp_coeff_parsed_alg *blk)
1150 {
1151 	const struct wmfw_adsp_alg_data *raw;
1152 	unsigned int data_len = le32_to_cpu(region->len);
1153 	unsigned int pos;
1154 	const u8 *tmp;
1155 
1156 	raw = (const struct wmfw_adsp_alg_data *)region->data;
1157 
1158 	switch (dsp->wmfw_ver) {
1159 	case 0:
1160 	case 1:
1161 		if (sizeof(*raw) > data_len)
1162 			return -EOVERFLOW;
1163 
1164 		blk->id = le32_to_cpu(raw->id);
1165 		blk->name = raw->name;
1166 		blk->name_len = strnlen(raw->name, ARRAY_SIZE(raw->name));
1167 		blk->ncoeff = le32_to_cpu(raw->ncoeff);
1168 
1169 		pos = sizeof(*raw);
1170 		break;
1171 	default:
1172 		if (sizeof(raw->id) > data_len)
1173 			return -EOVERFLOW;
1174 
1175 		tmp = region->data;
1176 		blk->id = cs_dsp_coeff_parse_int(sizeof(raw->id), &tmp);
1177 		pos = tmp - region->data;
1178 
1179 		tmp = &region->data[pos];
1180 		blk->name_len = cs_dsp_coeff_parse_string(sizeof(u8), &tmp, data_len - pos,
1181 							  &blk->name);
1182 		if (!tmp)
1183 			return -EOVERFLOW;
1184 
1185 		pos = tmp - region->data;
1186 		cs_dsp_coeff_parse_string(sizeof(u16), &tmp, data_len - pos, NULL);
1187 		if (!tmp)
1188 			return -EOVERFLOW;
1189 
1190 		pos = tmp - region->data;
1191 		if (sizeof(raw->ncoeff) > (data_len - pos))
1192 			return -EOVERFLOW;
1193 
1194 		blk->ncoeff = cs_dsp_coeff_parse_int(sizeof(raw->ncoeff), &tmp);
1195 		pos += sizeof(raw->ncoeff);
1196 		break;
1197 	}
1198 
1199 	if ((int)blk->ncoeff < 0)
1200 		return -EOVERFLOW;
1201 
1202 	cs_dsp_dbg(dsp, "Algorithm ID: %#x\n", blk->id);
1203 	cs_dsp_dbg(dsp, "Algorithm name: %.*s\n", blk->name_len, blk->name);
1204 	cs_dsp_dbg(dsp, "# of coefficient descriptors: %#x\n", blk->ncoeff);
1205 
1206 	return pos;
1207 }
1208 
1209 static int cs_dsp_coeff_parse_coeff(struct cs_dsp *dsp,
1210 				    const struct wmfw_region *region,
1211 				    unsigned int pos,
1212 				    struct cs_dsp_coeff_parsed_coeff *blk)
1213 {
1214 	const struct wmfw_adsp_coeff_data *raw;
1215 	unsigned int data_len = le32_to_cpu(region->len);
1216 	unsigned int blk_len, blk_end_pos;
1217 	const u8 *tmp;
1218 
1219 	raw = (const struct wmfw_adsp_coeff_data *)&region->data[pos];
1220 	if (sizeof(raw->hdr) > (data_len - pos))
1221 		return -EOVERFLOW;
1222 
1223 	blk_len = le32_to_cpu(raw->hdr.size);
1224 	if (blk_len > S32_MAX)
1225 		return -EOVERFLOW;
1226 
1227 	if (blk_len > (data_len - pos - sizeof(raw->hdr)))
1228 		return -EOVERFLOW;
1229 
1230 	blk_end_pos = pos + sizeof(raw->hdr) + blk_len;
1231 
1232 	blk->offset = le16_to_cpu(raw->hdr.offset);
1233 	blk->mem_type = le16_to_cpu(raw->hdr.type);
1234 
1235 	switch (dsp->wmfw_ver) {
1236 	case 0:
1237 	case 1:
1238 		if (sizeof(*raw) > (data_len - pos))
1239 			return -EOVERFLOW;
1240 
1241 		blk->name = raw->name;
1242 		blk->name_len = strnlen(raw->name, ARRAY_SIZE(raw->name));
1243 		blk->ctl_type = le16_to_cpu(raw->ctl_type);
1244 		blk->flags = le16_to_cpu(raw->flags);
1245 		blk->len = le32_to_cpu(raw->len);
1246 		break;
1247 	default:
1248 		pos += sizeof(raw->hdr);
1249 		tmp = &region->data[pos];
1250 		blk->name_len = cs_dsp_coeff_parse_string(sizeof(u8), &tmp, data_len - pos,
1251 							  &blk->name);
1252 		if (!tmp)
1253 			return -EOVERFLOW;
1254 
1255 		pos = tmp - region->data;
1256 		cs_dsp_coeff_parse_string(sizeof(u8), &tmp, data_len - pos, NULL);
1257 		if (!tmp)
1258 			return -EOVERFLOW;
1259 
1260 		pos = tmp - region->data;
1261 		cs_dsp_coeff_parse_string(sizeof(u16), &tmp, data_len - pos, NULL);
1262 		if (!tmp)
1263 			return -EOVERFLOW;
1264 
1265 		pos = tmp - region->data;
1266 		if (sizeof(raw->ctl_type) + sizeof(raw->flags) + sizeof(raw->len) >
1267 		    (data_len - pos))
1268 			return -EOVERFLOW;
1269 
1270 		blk->ctl_type = cs_dsp_coeff_parse_int(sizeof(raw->ctl_type), &tmp);
1271 		pos += sizeof(raw->ctl_type);
1272 		blk->flags = cs_dsp_coeff_parse_int(sizeof(raw->flags), &tmp);
1273 		pos += sizeof(raw->flags);
1274 		blk->len = cs_dsp_coeff_parse_int(sizeof(raw->len), &tmp);
1275 		break;
1276 	}
1277 
1278 	cs_dsp_dbg(dsp, "\tCoefficient type: %#x\n", blk->mem_type);
1279 	cs_dsp_dbg(dsp, "\tCoefficient offset: %#x\n", blk->offset);
1280 	cs_dsp_dbg(dsp, "\tCoefficient name: %.*s\n", blk->name_len, blk->name);
1281 	cs_dsp_dbg(dsp, "\tCoefficient flags: %#x\n", blk->flags);
1282 	cs_dsp_dbg(dsp, "\tALSA control type: %#x\n", blk->ctl_type);
1283 	cs_dsp_dbg(dsp, "\tALSA control len: %#x\n", blk->len);
1284 
1285 	return blk_end_pos;
1286 }
1287 
1288 static int cs_dsp_check_coeff_flags(struct cs_dsp *dsp,
1289 				    const struct cs_dsp_coeff_parsed_coeff *coeff_blk,
1290 				    unsigned int f_required,
1291 				    unsigned int f_illegal)
1292 {
1293 	if ((coeff_blk->flags & f_illegal) ||
1294 	    ((coeff_blk->flags & f_required) != f_required)) {
1295 		cs_dsp_err(dsp, "Illegal flags 0x%x for control type 0x%x\n",
1296 			   coeff_blk->flags, coeff_blk->ctl_type);
1297 		return -EINVAL;
1298 	}
1299 
1300 	return 0;
1301 }
1302 
1303 static int cs_dsp_parse_coeff(struct cs_dsp *dsp,
1304 			      const struct wmfw_region *region)
1305 {
1306 	struct cs_dsp_alg_region alg_region = {};
1307 	struct cs_dsp_coeff_parsed_alg alg_blk;
1308 	struct cs_dsp_coeff_parsed_coeff coeff_blk;
1309 	int i, pos, ret;
1310 
1311 	pos = cs_dsp_coeff_parse_alg(dsp, region, &alg_blk);
1312 	if (pos < 0)
1313 		return pos;
1314 
1315 	for (i = 0; i < alg_blk.ncoeff; i++) {
1316 		pos = cs_dsp_coeff_parse_coeff(dsp, region, pos, &coeff_blk);
1317 		if (pos < 0)
1318 			return pos;
1319 
1320 		switch (coeff_blk.ctl_type) {
1321 		case WMFW_CTL_TYPE_BYTES:
1322 			break;
1323 		case WMFW_CTL_TYPE_ACKED:
1324 			if (coeff_blk.flags & WMFW_CTL_FLAG_SYS)
1325 				continue;	/* ignore */
1326 
1327 			ret = cs_dsp_check_coeff_flags(dsp, &coeff_blk,
1328 						       WMFW_CTL_FLAG_VOLATILE |
1329 						       WMFW_CTL_FLAG_WRITEABLE |
1330 						       WMFW_CTL_FLAG_READABLE,
1331 						       0);
1332 			if (ret)
1333 				return -EINVAL;
1334 			break;
1335 		case WMFW_CTL_TYPE_HOSTEVENT:
1336 		case WMFW_CTL_TYPE_FWEVENT:
1337 			ret = cs_dsp_check_coeff_flags(dsp, &coeff_blk,
1338 						       WMFW_CTL_FLAG_SYS |
1339 						       WMFW_CTL_FLAG_VOLATILE |
1340 						       WMFW_CTL_FLAG_WRITEABLE |
1341 						       WMFW_CTL_FLAG_READABLE,
1342 						       0);
1343 			if (ret)
1344 				return -EINVAL;
1345 			break;
1346 		case WMFW_CTL_TYPE_HOST_BUFFER:
1347 			ret = cs_dsp_check_coeff_flags(dsp, &coeff_blk,
1348 						       WMFW_CTL_FLAG_SYS |
1349 						       WMFW_CTL_FLAG_VOLATILE |
1350 						       WMFW_CTL_FLAG_READABLE,
1351 						       0);
1352 			if (ret)
1353 				return -EINVAL;
1354 			break;
1355 		default:
1356 			cs_dsp_err(dsp, "Unknown control type: %d\n",
1357 				   coeff_blk.ctl_type);
1358 			return -EINVAL;
1359 		}
1360 
1361 		alg_region.type = coeff_blk.mem_type;
1362 		alg_region.alg = alg_blk.id;
1363 
1364 		ret = cs_dsp_create_control(dsp, &alg_region,
1365 					    coeff_blk.offset,
1366 					    coeff_blk.len,
1367 					    coeff_blk.name,
1368 					    coeff_blk.name_len,
1369 					    coeff_blk.flags,
1370 					    coeff_blk.ctl_type);
1371 		if (ret < 0)
1372 			cs_dsp_err(dsp, "Failed to create control: %.*s, %d\n",
1373 				   coeff_blk.name_len, coeff_blk.name, ret);
1374 	}
1375 
1376 	return 0;
1377 }
1378 
1379 static unsigned int cs_dsp_adsp1_parse_sizes(struct cs_dsp *dsp,
1380 					     const char * const file,
1381 					     unsigned int pos,
1382 					     const struct firmware *firmware)
1383 {
1384 	const struct wmfw_adsp1_sizes *adsp1_sizes;
1385 
1386 	adsp1_sizes = (void *)&firmware->data[pos];
1387 	if (sizeof(*adsp1_sizes) > firmware->size - pos) {
1388 		cs_dsp_err(dsp, "%s: file truncated\n", file);
1389 		return 0;
1390 	}
1391 
1392 	cs_dsp_dbg(dsp, "%s: %d DM, %d PM, %d ZM\n", file,
1393 		   le32_to_cpu(adsp1_sizes->dm), le32_to_cpu(adsp1_sizes->pm),
1394 		   le32_to_cpu(adsp1_sizes->zm));
1395 
1396 	return pos + sizeof(*adsp1_sizes);
1397 }
1398 
1399 static unsigned int cs_dsp_adsp2_parse_sizes(struct cs_dsp *dsp,
1400 					     const char * const file,
1401 					     unsigned int pos,
1402 					     const struct firmware *firmware)
1403 {
1404 	const struct wmfw_adsp2_sizes *adsp2_sizes;
1405 
1406 	adsp2_sizes = (void *)&firmware->data[pos];
1407 	if (sizeof(*adsp2_sizes) > firmware->size - pos) {
1408 		cs_dsp_err(dsp, "%s: file truncated\n", file);
1409 		return 0;
1410 	}
1411 
1412 	cs_dsp_dbg(dsp, "%s: %d XM, %d YM %d PM, %d ZM\n", file,
1413 		   le32_to_cpu(adsp2_sizes->xm), le32_to_cpu(adsp2_sizes->ym),
1414 		   le32_to_cpu(adsp2_sizes->pm), le32_to_cpu(adsp2_sizes->zm));
1415 
1416 	return pos + sizeof(*adsp2_sizes);
1417 }
1418 
1419 static bool cs_dsp_validate_version(struct cs_dsp *dsp, unsigned int version)
1420 {
1421 	switch (version) {
1422 	case 0:
1423 		cs_dsp_warn(dsp, "Deprecated file format %d\n", version);
1424 		return true;
1425 	case 1:
1426 	case 2:
1427 		return true;
1428 	default:
1429 		return false;
1430 	}
1431 }
1432 
1433 static bool cs_dsp_halo_validate_version(struct cs_dsp *dsp, unsigned int version)
1434 {
1435 	switch (version) {
1436 	case 3:
1437 		return true;
1438 	default:
1439 		return false;
1440 	}
1441 }
1442 
1443 static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware,
1444 		       const char *file)
1445 {
1446 	LIST_HEAD(buf_list);
1447 	struct regmap *regmap = dsp->regmap;
1448 	unsigned int pos = 0;
1449 	const struct wmfw_header *header;
1450 	const struct wmfw_footer *footer;
1451 	const struct wmfw_region *region;
1452 	const struct cs_dsp_region *mem;
1453 	const char *region_name;
1454 	u8 *buf = NULL;
1455 	size_t buf_len = 0;
1456 	size_t region_len;
1457 	unsigned int reg;
1458 	int regions = 0;
1459 	int ret, offset, type;
1460 
1461 	if (!firmware)
1462 		return 0;
1463 
1464 	ret = -EINVAL;
1465 
1466 	if (sizeof(*header) >= firmware->size) {
1467 		ret = -EOVERFLOW;
1468 		goto out_fw;
1469 	}
1470 
1471 	header = (void *)&firmware->data[0];
1472 
1473 	if (memcmp(&header->magic[0], "WMFW", 4) != 0) {
1474 		cs_dsp_err(dsp, "%s: invalid magic\n", file);
1475 		goto out_fw;
1476 	}
1477 
1478 	if (!dsp->ops->validate_version(dsp, header->ver)) {
1479 		cs_dsp_err(dsp, "%s: unknown file format %d\n",
1480 			   file, header->ver);
1481 		goto out_fw;
1482 	}
1483 
1484 	dsp->wmfw_ver = header->ver;
1485 
1486 	if (header->core != dsp->type) {
1487 		cs_dsp_err(dsp, "%s: invalid core %d != %d\n",
1488 			   file, header->core, dsp->type);
1489 		goto out_fw;
1490 	}
1491 
1492 	pos = sizeof(*header);
1493 	pos = dsp->ops->parse_sizes(dsp, file, pos, firmware);
1494 	if ((pos == 0) || (sizeof(*footer) > firmware->size - pos)) {
1495 		ret = -EOVERFLOW;
1496 		goto out_fw;
1497 	}
1498 
1499 	footer = (void *)&firmware->data[pos];
1500 	pos += sizeof(*footer);
1501 
1502 	if (le32_to_cpu(header->len) != pos) {
1503 		ret = -EOVERFLOW;
1504 		goto out_fw;
1505 	}
1506 
1507 	cs_dsp_info(dsp, "%s: format %d timestamp %#llx\n", file, header->ver,
1508 		    le64_to_cpu(footer->timestamp));
1509 
1510 	while (pos < firmware->size) {
1511 		/* Is there enough data for a complete block header? */
1512 		if (sizeof(*region) > firmware->size - pos) {
1513 			ret = -EOVERFLOW;
1514 			goto out_fw;
1515 		}
1516 
1517 		region = (void *)&(firmware->data[pos]);
1518 
1519 		if (le32_to_cpu(region->len) > firmware->size - pos - sizeof(*region)) {
1520 			ret = -EOVERFLOW;
1521 			goto out_fw;
1522 		}
1523 
1524 		region_name = "Unknown";
1525 		reg = 0;
1526 		offset = le32_to_cpu(region->offset) & 0xffffff;
1527 		type = be32_to_cpu(region->type) & 0xff;
1528 
1529 		switch (type) {
1530 		case WMFW_INFO_TEXT:
1531 		case WMFW_NAME_TEXT:
1532 			region_name = "Info/Name";
1533 			cs_dsp_info(dsp, "%s: %.*s\n", file,
1534 				    min(le32_to_cpu(region->len), 100), region->data);
1535 			break;
1536 		case WMFW_ALGORITHM_DATA:
1537 			region_name = "Algorithm";
1538 			ret = cs_dsp_parse_coeff(dsp, region);
1539 			if (ret != 0)
1540 				goto out_fw;
1541 			break;
1542 		case WMFW_ABSOLUTE:
1543 			region_name = "Absolute";
1544 			reg = offset;
1545 			break;
1546 		case WMFW_ADSP1_PM:
1547 		case WMFW_ADSP1_DM:
1548 		case WMFW_ADSP2_XM:
1549 		case WMFW_ADSP2_YM:
1550 		case WMFW_ADSP1_ZM:
1551 		case WMFW_HALO_PM_PACKED:
1552 		case WMFW_HALO_XM_PACKED:
1553 		case WMFW_HALO_YM_PACKED:
1554 			mem = cs_dsp_find_region(dsp, type);
1555 			if (!mem) {
1556 				cs_dsp_err(dsp, "No region of type: %x\n", type);
1557 				ret = -EINVAL;
1558 				goto out_fw;
1559 			}
1560 
1561 			region_name = cs_dsp_mem_region_name(type);
1562 			reg = dsp->ops->region_to_reg(mem, offset);
1563 			break;
1564 		default:
1565 			cs_dsp_warn(dsp,
1566 				    "%s.%d: Unknown region type %x at %d(%x)\n",
1567 				    file, regions, type, pos, pos);
1568 			break;
1569 		}
1570 
1571 		cs_dsp_dbg(dsp, "%s.%d: %d bytes at %d in %s\n", file,
1572 			   regions, le32_to_cpu(region->len), offset,
1573 			   region_name);
1574 
1575 		if (reg) {
1576 			region_len = le32_to_cpu(region->len);
1577 			if (region_len > buf_len) {
1578 				buf_len = round_up(region_len, PAGE_SIZE);
1579 				kfree(buf);
1580 				buf = kmalloc(buf_len, GFP_KERNEL | GFP_DMA);
1581 				if (!buf) {
1582 					ret = -ENOMEM;
1583 					goto out_fw;
1584 				}
1585 			}
1586 
1587 			memcpy(buf, region->data, region_len);
1588 			ret = regmap_raw_write(regmap, reg, buf, region_len);
1589 			if (ret != 0) {
1590 				cs_dsp_err(dsp,
1591 					   "%s.%d: Failed to write %zu bytes at %d in %s: %d\n",
1592 					   file, regions, region_len, offset, region_name, ret);
1593 				goto out_fw;
1594 			}
1595 		}
1596 
1597 		pos += le32_to_cpu(region->len) + sizeof(*region);
1598 		regions++;
1599 	}
1600 
1601 	if (pos > firmware->size)
1602 		cs_dsp_warn(dsp, "%s.%d: %zu bytes at end of file\n",
1603 			    file, regions, pos - firmware->size);
1604 
1605 	cs_dsp_debugfs_save_wmfwname(dsp, file);
1606 
1607 	ret = 0;
1608 out_fw:
1609 	kfree(buf);
1610 
1611 	if (ret == -EOVERFLOW)
1612 		cs_dsp_err(dsp, "%s: file content overflows file data\n", file);
1613 
1614 	return ret;
1615 }
1616 
1617 /**
1618  * cs_dsp_get_ctl() - Finds a matching coefficient control
1619  * @dsp: pointer to DSP structure
1620  * @name: pointer to string to match with a control's subname
1621  * @type: the algorithm type to match
1622  * @alg: the algorithm id to match
1623  *
1624  * Find cs_dsp_coeff_ctl with input name as its subname
1625  *
1626  * Return: pointer to the control on success, NULL if not found
1627  */
1628 struct cs_dsp_coeff_ctl *cs_dsp_get_ctl(struct cs_dsp *dsp, const char *name, int type,
1629 					unsigned int alg)
1630 {
1631 	struct cs_dsp_coeff_ctl *pos, *rslt = NULL;
1632 
1633 	lockdep_assert_held(&dsp->pwr_lock);
1634 
1635 	list_for_each_entry(pos, &dsp->ctl_list, list) {
1636 		if (!pos->subname)
1637 			continue;
1638 		if (strncmp(pos->subname, name, pos->subname_len) == 0 &&
1639 		    pos->fw_name == dsp->fw_name &&
1640 		    pos->alg_region.alg == alg &&
1641 		    pos->alg_region.type == type) {
1642 			rslt = pos;
1643 			break;
1644 		}
1645 	}
1646 
1647 	return rslt;
1648 }
1649 EXPORT_SYMBOL_NS_GPL(cs_dsp_get_ctl, "FW_CS_DSP");
1650 
1651 static void cs_dsp_ctl_fixup_base(struct cs_dsp *dsp,
1652 				  const struct cs_dsp_alg_region *alg_region)
1653 {
1654 	struct cs_dsp_coeff_ctl *ctl;
1655 
1656 	list_for_each_entry(ctl, &dsp->ctl_list, list) {
1657 		if (ctl->fw_name == dsp->fw_name &&
1658 		    alg_region->alg == ctl->alg_region.alg &&
1659 		    alg_region->type == ctl->alg_region.type) {
1660 			ctl->alg_region.base = alg_region->base;
1661 		}
1662 	}
1663 }
1664 
1665 static void *cs_dsp_read_algs(struct cs_dsp *dsp, size_t n_algs,
1666 			      const struct cs_dsp_region *mem,
1667 			      unsigned int pos, unsigned int len)
1668 {
1669 	void *alg;
1670 	unsigned int reg;
1671 	int ret;
1672 	__be32 val;
1673 
1674 	if (n_algs == 0) {
1675 		cs_dsp_err(dsp, "No algorithms\n");
1676 		return ERR_PTR(-EINVAL);
1677 	}
1678 
1679 	if (n_algs > 1024) {
1680 		cs_dsp_err(dsp, "Algorithm count %zx excessive\n", n_algs);
1681 		return ERR_PTR(-EINVAL);
1682 	}
1683 
1684 	/* Read the terminator first to validate the length */
1685 	reg = dsp->ops->region_to_reg(mem, pos + len);
1686 
1687 	ret = regmap_raw_read(dsp->regmap, reg, &val, sizeof(val));
1688 	if (ret != 0) {
1689 		cs_dsp_err(dsp, "Failed to read algorithm list end: %d\n",
1690 			   ret);
1691 		return ERR_PTR(ret);
1692 	}
1693 
1694 	if (be32_to_cpu(val) != 0xbedead)
1695 		cs_dsp_warn(dsp, "Algorithm list end %x 0x%x != 0xbedead\n",
1696 			    reg, be32_to_cpu(val));
1697 
1698 	/* Convert length from DSP words to bytes */
1699 	len *= sizeof(u32);
1700 
1701 	alg = kzalloc(len, GFP_KERNEL | GFP_DMA);
1702 	if (!alg)
1703 		return ERR_PTR(-ENOMEM);
1704 
1705 	reg = dsp->ops->region_to_reg(mem, pos);
1706 
1707 	ret = regmap_raw_read(dsp->regmap, reg, alg, len);
1708 	if (ret != 0) {
1709 		cs_dsp_err(dsp, "Failed to read algorithm list: %d\n", ret);
1710 		kfree(alg);
1711 		return ERR_PTR(ret);
1712 	}
1713 
1714 	return alg;
1715 }
1716 
1717 /**
1718  * cs_dsp_find_alg_region() - Finds a matching algorithm region
1719  * @dsp: pointer to DSP structure
1720  * @type: the algorithm type to match
1721  * @id: the algorithm id to match
1722  *
1723  * Return: Pointer to matching algorithm region, or NULL if not found.
1724  */
1725 struct cs_dsp_alg_region *cs_dsp_find_alg_region(struct cs_dsp *dsp,
1726 						 int type, unsigned int id)
1727 {
1728 	struct cs_dsp_alg_region_list_item *item;
1729 
1730 	lockdep_assert_held(&dsp->pwr_lock);
1731 
1732 	list_for_each_entry(item, &dsp->alg_regions, list) {
1733 		if (id == item->alg_region.alg && type == item->alg_region.type)
1734 			return &item->alg_region;
1735 	}
1736 
1737 	return NULL;
1738 }
1739 EXPORT_SYMBOL_NS_GPL(cs_dsp_find_alg_region, "FW_CS_DSP");
1740 
1741 static struct cs_dsp_alg_region *cs_dsp_create_region(struct cs_dsp *dsp,
1742 						      int type, __be32 id,
1743 						      __be32 ver, __be32 base)
1744 {
1745 	struct cs_dsp_alg_region_list_item *item;
1746 
1747 	item = kzalloc(sizeof(*item), GFP_KERNEL);
1748 	if (!item)
1749 		return ERR_PTR(-ENOMEM);
1750 
1751 	item->alg_region.type = type;
1752 	item->alg_region.alg = be32_to_cpu(id);
1753 	item->alg_region.ver = be32_to_cpu(ver);
1754 	item->alg_region.base = be32_to_cpu(base);
1755 
1756 	list_add_tail(&item->list, &dsp->alg_regions);
1757 
1758 	if (dsp->wmfw_ver > 0)
1759 		cs_dsp_ctl_fixup_base(dsp, &item->alg_region);
1760 
1761 	return &item->alg_region;
1762 }
1763 
1764 static void cs_dsp_free_alg_regions(struct cs_dsp *dsp)
1765 {
1766 	struct cs_dsp_alg_region_list_item *item;
1767 
1768 	while (!list_empty(&dsp->alg_regions)) {
1769 		item = list_first_entry(&dsp->alg_regions,
1770 					struct cs_dsp_alg_region_list_item,
1771 					list);
1772 		list_del(&item->list);
1773 		kfree(item);
1774 	}
1775 }
1776 
1777 static void cs_dsp_parse_wmfw_id_header(struct cs_dsp *dsp,
1778 					struct wmfw_id_hdr *fw, int nalgs)
1779 {
1780 	dsp->fw_id = be32_to_cpu(fw->id);
1781 	dsp->fw_id_version = be32_to_cpu(fw->ver);
1782 
1783 	cs_dsp_info(dsp, "Firmware: %x v%d.%d.%d, %d algorithms\n",
1784 		    dsp->fw_id, (dsp->fw_id_version & 0xff0000) >> 16,
1785 		    (dsp->fw_id_version & 0xff00) >> 8, dsp->fw_id_version & 0xff,
1786 		    nalgs);
1787 }
1788 
1789 static void cs_dsp_parse_wmfw_v3_id_header(struct cs_dsp *dsp,
1790 					   struct wmfw_v3_id_hdr *fw, int nalgs)
1791 {
1792 	dsp->fw_id = be32_to_cpu(fw->id);
1793 	dsp->fw_id_version = be32_to_cpu(fw->ver);
1794 	dsp->fw_vendor_id = be32_to_cpu(fw->vendor_id);
1795 
1796 	cs_dsp_info(dsp, "Firmware: %x vendor: 0x%x v%d.%d.%d, %d algorithms\n",
1797 		    dsp->fw_id, dsp->fw_vendor_id,
1798 		    (dsp->fw_id_version & 0xff0000) >> 16,
1799 		    (dsp->fw_id_version & 0xff00) >> 8, dsp->fw_id_version & 0xff,
1800 		    nalgs);
1801 }
1802 
1803 static int cs_dsp_create_regions(struct cs_dsp *dsp, __be32 id, __be32 ver,
1804 				 int nregions, const int *type, __be32 *base)
1805 {
1806 	struct cs_dsp_alg_region *alg_region;
1807 	int i;
1808 
1809 	for (i = 0; i < nregions; i++) {
1810 		alg_region = cs_dsp_create_region(dsp, type[i], id, ver, base[i]);
1811 		if (IS_ERR(alg_region))
1812 			return PTR_ERR(alg_region);
1813 	}
1814 
1815 	return 0;
1816 }
1817 
1818 static int cs_dsp_adsp1_setup_algs(struct cs_dsp *dsp)
1819 {
1820 	struct wmfw_adsp1_id_hdr adsp1_id;
1821 	struct wmfw_adsp1_alg_hdr *adsp1_alg;
1822 	struct cs_dsp_alg_region *alg_region;
1823 	const struct cs_dsp_region *mem;
1824 	unsigned int pos, len;
1825 	size_t n_algs;
1826 	int i, ret;
1827 
1828 	mem = cs_dsp_find_region(dsp, WMFW_ADSP1_DM);
1829 	if (WARN_ON(!mem))
1830 		return -EINVAL;
1831 
1832 	ret = regmap_raw_read(dsp->regmap, mem->base, &adsp1_id,
1833 			      sizeof(adsp1_id));
1834 	if (ret != 0) {
1835 		cs_dsp_err(dsp, "Failed to read algorithm info: %d\n",
1836 			   ret);
1837 		return ret;
1838 	}
1839 
1840 	n_algs = be32_to_cpu(adsp1_id.n_algs);
1841 
1842 	cs_dsp_parse_wmfw_id_header(dsp, &adsp1_id.fw, n_algs);
1843 
1844 	alg_region = cs_dsp_create_region(dsp, WMFW_ADSP1_ZM,
1845 					  adsp1_id.fw.id, adsp1_id.fw.ver,
1846 					  adsp1_id.zm);
1847 	if (IS_ERR(alg_region))
1848 		return PTR_ERR(alg_region);
1849 
1850 	alg_region = cs_dsp_create_region(dsp, WMFW_ADSP1_DM,
1851 					  adsp1_id.fw.id, adsp1_id.fw.ver,
1852 					  adsp1_id.dm);
1853 	if (IS_ERR(alg_region))
1854 		return PTR_ERR(alg_region);
1855 
1856 	/* Calculate offset and length in DSP words */
1857 	pos = sizeof(adsp1_id) / sizeof(u32);
1858 	len = (sizeof(*adsp1_alg) * n_algs) / sizeof(u32);
1859 
1860 	adsp1_alg = cs_dsp_read_algs(dsp, n_algs, mem, pos, len);
1861 	if (IS_ERR(adsp1_alg))
1862 		return PTR_ERR(adsp1_alg);
1863 
1864 	for (i = 0; i < n_algs; i++) {
1865 		cs_dsp_info(dsp, "%d: ID %x v%d.%d.%d DM@%x ZM@%x\n",
1866 			    i, be32_to_cpu(adsp1_alg[i].alg.id),
1867 			    (be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff0000) >> 16,
1868 			    (be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff00) >> 8,
1869 			    be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff,
1870 			    be32_to_cpu(adsp1_alg[i].dm),
1871 			    be32_to_cpu(adsp1_alg[i].zm));
1872 
1873 		alg_region = cs_dsp_create_region(dsp, WMFW_ADSP1_DM,
1874 						  adsp1_alg[i].alg.id,
1875 						  adsp1_alg[i].alg.ver,
1876 						  adsp1_alg[i].dm);
1877 		if (IS_ERR(alg_region)) {
1878 			ret = PTR_ERR(alg_region);
1879 			goto out;
1880 		}
1881 		if (dsp->wmfw_ver == 0) {
1882 			if (i + 1 < n_algs) {
1883 				len = be32_to_cpu(adsp1_alg[i + 1].dm);
1884 				len -= be32_to_cpu(adsp1_alg[i].dm);
1885 				len *= 4;
1886 				cs_dsp_create_control(dsp, alg_region, 0,
1887 						      len, NULL, 0, 0,
1888 						      WMFW_CTL_TYPE_BYTES);
1889 			} else {
1890 				cs_dsp_warn(dsp, "Missing length info for region DM with ID %x\n",
1891 					    be32_to_cpu(adsp1_alg[i].alg.id));
1892 			}
1893 		}
1894 
1895 		alg_region = cs_dsp_create_region(dsp, WMFW_ADSP1_ZM,
1896 						  adsp1_alg[i].alg.id,
1897 						  adsp1_alg[i].alg.ver,
1898 						  adsp1_alg[i].zm);
1899 		if (IS_ERR(alg_region)) {
1900 			ret = PTR_ERR(alg_region);
1901 			goto out;
1902 		}
1903 		if (dsp->wmfw_ver == 0) {
1904 			if (i + 1 < n_algs) {
1905 				len = be32_to_cpu(adsp1_alg[i + 1].zm);
1906 				len -= be32_to_cpu(adsp1_alg[i].zm);
1907 				len *= 4;
1908 				cs_dsp_create_control(dsp, alg_region, 0,
1909 						      len, NULL, 0, 0,
1910 						      WMFW_CTL_TYPE_BYTES);
1911 			} else {
1912 				cs_dsp_warn(dsp, "Missing length info for region ZM with ID %x\n",
1913 					    be32_to_cpu(adsp1_alg[i].alg.id));
1914 			}
1915 		}
1916 	}
1917 
1918 out:
1919 	kfree(adsp1_alg);
1920 	return ret;
1921 }
1922 
1923 static int cs_dsp_adsp2_setup_algs(struct cs_dsp *dsp)
1924 {
1925 	struct wmfw_adsp2_id_hdr adsp2_id;
1926 	struct wmfw_adsp2_alg_hdr *adsp2_alg;
1927 	struct cs_dsp_alg_region *alg_region;
1928 	const struct cs_dsp_region *mem;
1929 	unsigned int pos, len;
1930 	size_t n_algs;
1931 	int i, ret;
1932 
1933 	mem = cs_dsp_find_region(dsp, WMFW_ADSP2_XM);
1934 	if (WARN_ON(!mem))
1935 		return -EINVAL;
1936 
1937 	ret = regmap_raw_read(dsp->regmap, mem->base, &adsp2_id,
1938 			      sizeof(adsp2_id));
1939 	if (ret != 0) {
1940 		cs_dsp_err(dsp, "Failed to read algorithm info: %d\n",
1941 			   ret);
1942 		return ret;
1943 	}
1944 
1945 	n_algs = be32_to_cpu(adsp2_id.n_algs);
1946 
1947 	cs_dsp_parse_wmfw_id_header(dsp, &adsp2_id.fw, n_algs);
1948 
1949 	alg_region = cs_dsp_create_region(dsp, WMFW_ADSP2_XM,
1950 					  adsp2_id.fw.id, adsp2_id.fw.ver,
1951 					  adsp2_id.xm);
1952 	if (IS_ERR(alg_region))
1953 		return PTR_ERR(alg_region);
1954 
1955 	alg_region = cs_dsp_create_region(dsp, WMFW_ADSP2_YM,
1956 					  adsp2_id.fw.id, adsp2_id.fw.ver,
1957 					  adsp2_id.ym);
1958 	if (IS_ERR(alg_region))
1959 		return PTR_ERR(alg_region);
1960 
1961 	alg_region = cs_dsp_create_region(dsp, WMFW_ADSP2_ZM,
1962 					  adsp2_id.fw.id, adsp2_id.fw.ver,
1963 					  adsp2_id.zm);
1964 	if (IS_ERR(alg_region))
1965 		return PTR_ERR(alg_region);
1966 
1967 	/* Calculate offset and length in DSP words */
1968 	pos = sizeof(adsp2_id) / sizeof(u32);
1969 	len = (sizeof(*adsp2_alg) * n_algs) / sizeof(u32);
1970 
1971 	adsp2_alg = cs_dsp_read_algs(dsp, n_algs, mem, pos, len);
1972 	if (IS_ERR(adsp2_alg))
1973 		return PTR_ERR(adsp2_alg);
1974 
1975 	for (i = 0; i < n_algs; i++) {
1976 		cs_dsp_dbg(dsp,
1977 			   "%d: ID %x v%d.%d.%d XM@%x YM@%x ZM@%x\n",
1978 			   i, be32_to_cpu(adsp2_alg[i].alg.id),
1979 			   (be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff0000) >> 16,
1980 			   (be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff00) >> 8,
1981 			   be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff,
1982 			   be32_to_cpu(adsp2_alg[i].xm),
1983 			   be32_to_cpu(adsp2_alg[i].ym),
1984 			   be32_to_cpu(adsp2_alg[i].zm));
1985 
1986 		alg_region = cs_dsp_create_region(dsp, WMFW_ADSP2_XM,
1987 						  adsp2_alg[i].alg.id,
1988 						  adsp2_alg[i].alg.ver,
1989 						  adsp2_alg[i].xm);
1990 		if (IS_ERR(alg_region)) {
1991 			ret = PTR_ERR(alg_region);
1992 			goto out;
1993 		}
1994 		if (dsp->wmfw_ver == 0) {
1995 			if (i + 1 < n_algs) {
1996 				len = be32_to_cpu(adsp2_alg[i + 1].xm);
1997 				len -= be32_to_cpu(adsp2_alg[i].xm);
1998 				len *= 4;
1999 				cs_dsp_create_control(dsp, alg_region, 0,
2000 						      len, NULL, 0, 0,
2001 						      WMFW_CTL_TYPE_BYTES);
2002 			} else {
2003 				cs_dsp_warn(dsp, "Missing length info for region XM with ID %x\n",
2004 					    be32_to_cpu(adsp2_alg[i].alg.id));
2005 			}
2006 		}
2007 
2008 		alg_region = cs_dsp_create_region(dsp, WMFW_ADSP2_YM,
2009 						  adsp2_alg[i].alg.id,
2010 						  adsp2_alg[i].alg.ver,
2011 						  adsp2_alg[i].ym);
2012 		if (IS_ERR(alg_region)) {
2013 			ret = PTR_ERR(alg_region);
2014 			goto out;
2015 		}
2016 		if (dsp->wmfw_ver == 0) {
2017 			if (i + 1 < n_algs) {
2018 				len = be32_to_cpu(adsp2_alg[i + 1].ym);
2019 				len -= be32_to_cpu(adsp2_alg[i].ym);
2020 				len *= 4;
2021 				cs_dsp_create_control(dsp, alg_region, 0,
2022 						      len, NULL, 0, 0,
2023 						      WMFW_CTL_TYPE_BYTES);
2024 			} else {
2025 				cs_dsp_warn(dsp, "Missing length info for region YM with ID %x\n",
2026 					    be32_to_cpu(adsp2_alg[i].alg.id));
2027 			}
2028 		}
2029 
2030 		alg_region = cs_dsp_create_region(dsp, WMFW_ADSP2_ZM,
2031 						  adsp2_alg[i].alg.id,
2032 						  adsp2_alg[i].alg.ver,
2033 						  adsp2_alg[i].zm);
2034 		if (IS_ERR(alg_region)) {
2035 			ret = PTR_ERR(alg_region);
2036 			goto out;
2037 		}
2038 		if (dsp->wmfw_ver == 0) {
2039 			if (i + 1 < n_algs) {
2040 				len = be32_to_cpu(adsp2_alg[i + 1].zm);
2041 				len -= be32_to_cpu(adsp2_alg[i].zm);
2042 				len *= 4;
2043 				cs_dsp_create_control(dsp, alg_region, 0,
2044 						      len, NULL, 0, 0,
2045 						      WMFW_CTL_TYPE_BYTES);
2046 			} else {
2047 				cs_dsp_warn(dsp, "Missing length info for region ZM with ID %x\n",
2048 					    be32_to_cpu(adsp2_alg[i].alg.id));
2049 			}
2050 		}
2051 	}
2052 
2053 out:
2054 	kfree(adsp2_alg);
2055 	return ret;
2056 }
2057 
2058 static int cs_dsp_halo_create_regions(struct cs_dsp *dsp, __be32 id, __be32 ver,
2059 				      __be32 xm_base, __be32 ym_base)
2060 {
2061 	static const int types[] = {
2062 		WMFW_ADSP2_XM, WMFW_HALO_XM_PACKED,
2063 		WMFW_ADSP2_YM, WMFW_HALO_YM_PACKED
2064 	};
2065 	__be32 bases[] = { xm_base, xm_base, ym_base, ym_base };
2066 
2067 	return cs_dsp_create_regions(dsp, id, ver, ARRAY_SIZE(types), types, bases);
2068 }
2069 
2070 static int cs_dsp_halo_setup_algs(struct cs_dsp *dsp)
2071 {
2072 	struct wmfw_halo_id_hdr halo_id;
2073 	struct wmfw_halo_alg_hdr *halo_alg;
2074 	const struct cs_dsp_region *mem;
2075 	unsigned int pos, len;
2076 	size_t n_algs;
2077 	int i, ret;
2078 
2079 	mem = cs_dsp_find_region(dsp, WMFW_ADSP2_XM);
2080 	if (WARN_ON(!mem))
2081 		return -EINVAL;
2082 
2083 	ret = regmap_raw_read(dsp->regmap, mem->base, &halo_id,
2084 			      sizeof(halo_id));
2085 	if (ret != 0) {
2086 		cs_dsp_err(dsp, "Failed to read algorithm info: %d\n",
2087 			   ret);
2088 		return ret;
2089 	}
2090 
2091 	n_algs = be32_to_cpu(halo_id.n_algs);
2092 
2093 	cs_dsp_parse_wmfw_v3_id_header(dsp, &halo_id.fw, n_algs);
2094 
2095 	ret = cs_dsp_halo_create_regions(dsp, halo_id.fw.id, halo_id.fw.ver,
2096 					 halo_id.xm_base, halo_id.ym_base);
2097 	if (ret)
2098 		return ret;
2099 
2100 	/* Calculate offset and length in DSP words */
2101 	pos = sizeof(halo_id) / sizeof(u32);
2102 	len = (sizeof(*halo_alg) * n_algs) / sizeof(u32);
2103 
2104 	halo_alg = cs_dsp_read_algs(dsp, n_algs, mem, pos, len);
2105 	if (IS_ERR(halo_alg))
2106 		return PTR_ERR(halo_alg);
2107 
2108 	for (i = 0; i < n_algs; i++) {
2109 		cs_dsp_dbg(dsp,
2110 			   "%d: ID %x v%d.%d.%d XM@%x YM@%x\n",
2111 			   i, be32_to_cpu(halo_alg[i].alg.id),
2112 			   (be32_to_cpu(halo_alg[i].alg.ver) & 0xff0000) >> 16,
2113 			   (be32_to_cpu(halo_alg[i].alg.ver) & 0xff00) >> 8,
2114 			   be32_to_cpu(halo_alg[i].alg.ver) & 0xff,
2115 			   be32_to_cpu(halo_alg[i].xm_base),
2116 			   be32_to_cpu(halo_alg[i].ym_base));
2117 
2118 		ret = cs_dsp_halo_create_regions(dsp, halo_alg[i].alg.id,
2119 						 halo_alg[i].alg.ver,
2120 						 halo_alg[i].xm_base,
2121 						 halo_alg[i].ym_base);
2122 		if (ret)
2123 			goto out;
2124 	}
2125 
2126 out:
2127 	kfree(halo_alg);
2128 	return ret;
2129 }
2130 
2131 static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware,
2132 			     const char *file)
2133 {
2134 	LIST_HEAD(buf_list);
2135 	struct regmap *regmap = dsp->regmap;
2136 	struct wmfw_coeff_hdr *hdr;
2137 	struct wmfw_coeff_item *blk;
2138 	const struct cs_dsp_region *mem;
2139 	struct cs_dsp_alg_region *alg_region;
2140 	const char *region_name;
2141 	int ret, pos, blocks, type, version;
2142 	unsigned int offset, reg;
2143 	u8 *buf = NULL;
2144 	size_t buf_len = 0;
2145 	size_t region_len;
2146 
2147 	if (!firmware)
2148 		return 0;
2149 
2150 	ret = -EINVAL;
2151 
2152 	if (sizeof(*hdr) >= firmware->size) {
2153 		cs_dsp_err(dsp, "%s: coefficient file too short, %zu bytes\n",
2154 			   file, firmware->size);
2155 		goto out_fw;
2156 	}
2157 
2158 	hdr = (void *)&firmware->data[0];
2159 	if (memcmp(hdr->magic, "WMDR", 4) != 0) {
2160 		cs_dsp_err(dsp, "%s: invalid coefficient magic\n", file);
2161 		goto out_fw;
2162 	}
2163 
2164 	switch (be32_to_cpu(hdr->rev) & 0xff) {
2165 	case 1:
2166 	case 2:
2167 	case 3:
2168 		break;
2169 	default:
2170 		cs_dsp_err(dsp, "%s: Unsupported coefficient file format %d\n",
2171 			   file, be32_to_cpu(hdr->rev) & 0xff);
2172 		ret = -EINVAL;
2173 		goto out_fw;
2174 	}
2175 
2176 	cs_dsp_info(dsp, "%s (v%d): v%d.%d.%d\n", file,
2177 		    be32_to_cpu(hdr->rev) & 0xff,
2178 		    (le32_to_cpu(hdr->ver) >> 16) & 0xff,
2179 		    (le32_to_cpu(hdr->ver) >>  8) & 0xff,
2180 		    le32_to_cpu(hdr->ver) & 0xff);
2181 
2182 	pos = le32_to_cpu(hdr->len);
2183 
2184 	blocks = 0;
2185 	while (pos < firmware->size) {
2186 		/* Is there enough data for a complete block header? */
2187 		if (sizeof(*blk) > firmware->size - pos) {
2188 			ret = -EOVERFLOW;
2189 			goto out_fw;
2190 		}
2191 
2192 		blk = (void *)(&firmware->data[pos]);
2193 
2194 		if (le32_to_cpu(blk->len) > firmware->size - pos - sizeof(*blk)) {
2195 			ret = -EOVERFLOW;
2196 			goto out_fw;
2197 		}
2198 
2199 		type = le16_to_cpu(blk->type);
2200 		offset = le16_to_cpu(blk->offset);
2201 		version = le32_to_cpu(blk->ver) >> 8;
2202 
2203 		cs_dsp_dbg(dsp, "%s.%d: %x v%d.%d.%d\n",
2204 			   file, blocks, le32_to_cpu(blk->id),
2205 			   (le32_to_cpu(blk->ver) >> 16) & 0xff,
2206 			   (le32_to_cpu(blk->ver) >>  8) & 0xff,
2207 			   le32_to_cpu(blk->ver) & 0xff);
2208 		cs_dsp_dbg(dsp, "%s.%d: %d bytes off:%#x off32:%#x in %#x\n",
2209 			   file, blocks, le32_to_cpu(blk->len), offset,
2210 			   le32_to_cpu(blk->offset32), type);
2211 
2212 		reg = 0;
2213 		region_name = "Unknown";
2214 		switch (type) {
2215 		case (WMFW_NAME_TEXT << 8):
2216 			cs_dsp_info(dsp, "%s: %.*s\n", dsp->fw_name,
2217 				    min(le32_to_cpu(blk->len), 100), blk->data);
2218 			break;
2219 		case (WMFW_INFO_TEXT << 8):
2220 		case (WMFW_METADATA << 8):
2221 			break;
2222 		case (WMFW_ABSOLUTE << 8):
2223 			/*
2224 			 * Old files may use this for global
2225 			 * coefficients.
2226 			 */
2227 			if (le32_to_cpu(blk->id) == dsp->fw_id &&
2228 			    offset == 0) {
2229 				region_name = "global coefficients";
2230 				mem = cs_dsp_find_region(dsp, type);
2231 				if (!mem) {
2232 					cs_dsp_err(dsp, "No ZM\n");
2233 					break;
2234 				}
2235 				reg = dsp->ops->region_to_reg(mem, 0);
2236 
2237 			} else {
2238 				region_name = "register";
2239 				reg = offset;
2240 			}
2241 			break;
2242 
2243 		case WMFW_ADSP2_XM_LONG:
2244 		case WMFW_ADSP2_YM_LONG:
2245 		case WMFW_HALO_XM_PACKED_LONG:
2246 		case WMFW_HALO_YM_PACKED_LONG:
2247 			offset = le32_to_cpu(blk->offset32);
2248 			type &= 0xff; /* strip extended block type flags */
2249 			fallthrough;
2250 		case WMFW_ADSP1_DM:
2251 		case WMFW_ADSP1_ZM:
2252 		case WMFW_ADSP2_XM:
2253 		case WMFW_ADSP2_YM:
2254 		case WMFW_HALO_XM_PACKED:
2255 		case WMFW_HALO_YM_PACKED:
2256 		case WMFW_HALO_PM_PACKED:
2257 			cs_dsp_dbg(dsp, "%s.%d: %d bytes in %x for %x\n",
2258 				   file, blocks, le32_to_cpu(blk->len),
2259 				   type, le32_to_cpu(blk->id));
2260 
2261 			region_name = cs_dsp_mem_region_name(type);
2262 			mem = cs_dsp_find_region(dsp, type);
2263 			if (!mem) {
2264 				cs_dsp_err(dsp, "No base for region %x\n", type);
2265 				break;
2266 			}
2267 
2268 			alg_region = cs_dsp_find_alg_region(dsp, type,
2269 							    le32_to_cpu(blk->id));
2270 			if (alg_region) {
2271 				if (version != alg_region->ver)
2272 					cs_dsp_warn(dsp,
2273 						    "Algorithm coefficient version %d.%d.%d but expected %d.%d.%d\n",
2274 						   (version >> 16) & 0xFF,
2275 						   (version >> 8) & 0xFF,
2276 						   version & 0xFF,
2277 						   (alg_region->ver >> 16) & 0xFF,
2278 						   (alg_region->ver >> 8) & 0xFF,
2279 						   alg_region->ver & 0xFF);
2280 
2281 				reg = alg_region->base;
2282 				reg = dsp->ops->region_to_reg(mem, reg);
2283 				reg += offset;
2284 			} else {
2285 				cs_dsp_err(dsp, "No %s for algorithm %x\n",
2286 					   region_name, le32_to_cpu(blk->id));
2287 			}
2288 			break;
2289 
2290 		default:
2291 			cs_dsp_err(dsp, "%s.%d: Unknown region type %x at %d\n",
2292 				   file, blocks, type, pos);
2293 			break;
2294 		}
2295 
2296 		if (reg) {
2297 			region_len = le32_to_cpu(blk->len);
2298 			if (region_len > buf_len) {
2299 				buf_len = round_up(region_len, PAGE_SIZE);
2300 				kfree(buf);
2301 				buf = kmalloc(buf_len, GFP_KERNEL | GFP_DMA);
2302 				if (!buf) {
2303 					ret = -ENOMEM;
2304 					goto out_fw;
2305 				}
2306 			}
2307 
2308 			memcpy(buf, blk->data, region_len);
2309 
2310 			cs_dsp_dbg(dsp, "%s.%d: Writing %zu bytes at %x\n",
2311 				   file, blocks, region_len, reg);
2312 			ret = regmap_raw_write(regmap, reg, buf, region_len);
2313 			if (ret != 0) {
2314 				cs_dsp_err(dsp,
2315 					   "%s.%d: Failed to write to %x in %s: %d\n",
2316 					   file, blocks, reg, region_name, ret);
2317 			}
2318 		}
2319 
2320 		pos += (le32_to_cpu(blk->len) + sizeof(*blk) + 3) & ~0x03;
2321 		blocks++;
2322 	}
2323 
2324 	if (pos > firmware->size)
2325 		cs_dsp_warn(dsp, "%s.%d: %zu bytes at end of file\n",
2326 			    file, blocks, pos - firmware->size);
2327 
2328 	cs_dsp_debugfs_save_binname(dsp, file);
2329 
2330 	ret = 0;
2331 out_fw:
2332 	kfree(buf);
2333 
2334 	if (ret == -EOVERFLOW)
2335 		cs_dsp_err(dsp, "%s: file content overflows file data\n", file);
2336 
2337 	return ret;
2338 }
2339 
2340 static int cs_dsp_create_name(struct cs_dsp *dsp)
2341 {
2342 	if (!dsp->name) {
2343 		dsp->name = devm_kasprintf(dsp->dev, GFP_KERNEL, "DSP%d",
2344 					   dsp->num);
2345 		if (!dsp->name)
2346 			return -ENOMEM;
2347 	}
2348 
2349 	return 0;
2350 }
2351 
2352 static const struct cs_dsp_client_ops cs_dsp_default_client_ops = {
2353 };
2354 
2355 static int cs_dsp_common_init(struct cs_dsp *dsp)
2356 {
2357 	int ret;
2358 
2359 	ret = cs_dsp_create_name(dsp);
2360 	if (ret)
2361 		return ret;
2362 
2363 	INIT_LIST_HEAD(&dsp->alg_regions);
2364 	INIT_LIST_HEAD(&dsp->ctl_list);
2365 
2366 	mutex_init(&dsp->pwr_lock);
2367 
2368 	if (!dsp->client_ops)
2369 		dsp->client_ops = &cs_dsp_default_client_ops;
2370 
2371 #ifdef CONFIG_DEBUG_FS
2372 	/* Ensure this is invalid if client never provides a debugfs root */
2373 	dsp->debugfs_root = ERR_PTR(-ENODEV);
2374 #endif
2375 
2376 	return 0;
2377 }
2378 
2379 /**
2380  * cs_dsp_adsp1_init() - Initialise a cs_dsp structure representing a ADSP1 device
2381  * @dsp: pointer to DSP structure
2382  *
2383  * Return: Zero for success, a negative number on error.
2384  */
2385 int cs_dsp_adsp1_init(struct cs_dsp *dsp)
2386 {
2387 	dsp->ops = &cs_dsp_adsp1_ops;
2388 
2389 	return cs_dsp_common_init(dsp);
2390 }
2391 EXPORT_SYMBOL_NS_GPL(cs_dsp_adsp1_init, "FW_CS_DSP");
2392 
2393 /**
2394  * cs_dsp_adsp1_power_up() - Load and start the named firmware
2395  * @dsp: pointer to DSP structure
2396  * @wmfw_firmware: the firmware to be sent
2397  * @wmfw_filename: file name of firmware to be sent
2398  * @coeff_firmware: the coefficient data to be sent
2399  * @coeff_filename: file name of coefficient to data be sent
2400  * @fw_name: the user-friendly firmware name
2401  *
2402  * Return: Zero for success, a negative number on error.
2403  */
2404 int cs_dsp_adsp1_power_up(struct cs_dsp *dsp,
2405 			  const struct firmware *wmfw_firmware, const char *wmfw_filename,
2406 			  const struct firmware *coeff_firmware, const char *coeff_filename,
2407 			  const char *fw_name)
2408 {
2409 	unsigned int val;
2410 	int ret;
2411 
2412 	mutex_lock(&dsp->pwr_lock);
2413 
2414 	dsp->fw_name = fw_name;
2415 
2416 	regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
2417 			   ADSP1_SYS_ENA, ADSP1_SYS_ENA);
2418 
2419 	/*
2420 	 * For simplicity set the DSP clock rate to be the
2421 	 * SYSCLK rate rather than making it configurable.
2422 	 */
2423 	if (dsp->sysclk_reg) {
2424 		ret = regmap_read(dsp->regmap, dsp->sysclk_reg, &val);
2425 		if (ret != 0) {
2426 			cs_dsp_err(dsp, "Failed to read SYSCLK state: %d\n", ret);
2427 			goto err_mutex;
2428 		}
2429 
2430 		val = (val & dsp->sysclk_mask) >> dsp->sysclk_shift;
2431 
2432 		ret = regmap_update_bits(dsp->regmap,
2433 					 dsp->base + ADSP1_CONTROL_31,
2434 					 ADSP1_CLK_SEL_MASK, val);
2435 		if (ret != 0) {
2436 			cs_dsp_err(dsp, "Failed to set clock rate: %d\n", ret);
2437 			goto err_mutex;
2438 		}
2439 	}
2440 
2441 	ret = cs_dsp_load(dsp, wmfw_firmware, wmfw_filename);
2442 	if (ret != 0)
2443 		goto err_ena;
2444 
2445 	ret = cs_dsp_adsp1_setup_algs(dsp);
2446 	if (ret != 0)
2447 		goto err_ena;
2448 
2449 	ret = cs_dsp_load_coeff(dsp, coeff_firmware, coeff_filename);
2450 	if (ret != 0)
2451 		goto err_ena;
2452 
2453 	/* Initialize caches for enabled and unset controls */
2454 	ret = cs_dsp_coeff_init_control_caches(dsp);
2455 	if (ret != 0)
2456 		goto err_ena;
2457 
2458 	/* Sync set controls */
2459 	ret = cs_dsp_coeff_sync_controls(dsp);
2460 	if (ret != 0)
2461 		goto err_ena;
2462 
2463 	dsp->booted = true;
2464 
2465 	/* Start the core running */
2466 	regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
2467 			   ADSP1_CORE_ENA | ADSP1_START,
2468 			   ADSP1_CORE_ENA | ADSP1_START);
2469 
2470 	dsp->running = true;
2471 
2472 	mutex_unlock(&dsp->pwr_lock);
2473 
2474 	return 0;
2475 
2476 err_ena:
2477 	regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
2478 			   ADSP1_SYS_ENA, 0);
2479 err_mutex:
2480 	mutex_unlock(&dsp->pwr_lock);
2481 	return ret;
2482 }
2483 EXPORT_SYMBOL_NS_GPL(cs_dsp_adsp1_power_up, "FW_CS_DSP");
2484 
2485 /**
2486  * cs_dsp_adsp1_power_down() - Halts the DSP
2487  * @dsp: pointer to DSP structure
2488  */
2489 void cs_dsp_adsp1_power_down(struct cs_dsp *dsp)
2490 {
2491 	struct cs_dsp_coeff_ctl *ctl;
2492 
2493 	mutex_lock(&dsp->pwr_lock);
2494 
2495 	dsp->running = false;
2496 	dsp->booted = false;
2497 
2498 	/* Halt the core */
2499 	regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
2500 			   ADSP1_CORE_ENA | ADSP1_START, 0);
2501 
2502 	regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_19,
2503 			   ADSP1_WDMA_BUFFER_LENGTH_MASK, 0);
2504 
2505 	regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
2506 			   ADSP1_SYS_ENA, 0);
2507 
2508 	list_for_each_entry(ctl, &dsp->ctl_list, list)
2509 		ctl->enabled = 0;
2510 
2511 	cs_dsp_free_alg_regions(dsp);
2512 
2513 	mutex_unlock(&dsp->pwr_lock);
2514 }
2515 EXPORT_SYMBOL_NS_GPL(cs_dsp_adsp1_power_down, "FW_CS_DSP");
2516 
2517 static int cs_dsp_adsp2v2_enable_core(struct cs_dsp *dsp)
2518 {
2519 	unsigned int val;
2520 	int ret, count;
2521 
2522 	/* Wait for the RAM to start, should be near instantaneous */
2523 	for (count = 0; count < 10; ++count) {
2524 		ret = regmap_read(dsp->regmap, dsp->base + ADSP2_STATUS1, &val);
2525 		if (ret != 0)
2526 			return ret;
2527 
2528 		if (val & ADSP2_RAM_RDY)
2529 			break;
2530 
2531 		usleep_range(250, 500);
2532 	}
2533 
2534 	if (!(val & ADSP2_RAM_RDY)) {
2535 		cs_dsp_err(dsp, "Failed to start DSP RAM\n");
2536 		return -EBUSY;
2537 	}
2538 
2539 	cs_dsp_dbg(dsp, "RAM ready after %d polls\n", count);
2540 
2541 	return 0;
2542 }
2543 
2544 static int cs_dsp_adsp2_enable_core(struct cs_dsp *dsp)
2545 {
2546 	int ret;
2547 
2548 	ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
2549 				 ADSP2_SYS_ENA, ADSP2_SYS_ENA);
2550 	if (ret != 0)
2551 		return ret;
2552 
2553 	return cs_dsp_adsp2v2_enable_core(dsp);
2554 }
2555 
2556 static int cs_dsp_adsp2_lock(struct cs_dsp *dsp, unsigned int lock_regions)
2557 {
2558 	struct regmap *regmap = dsp->regmap;
2559 	unsigned int code0, code1, lock_reg;
2560 
2561 	if (!(lock_regions & CS_ADSP2_REGION_ALL))
2562 		return 0;
2563 
2564 	lock_regions &= CS_ADSP2_REGION_ALL;
2565 	lock_reg = dsp->base + ADSP2_LOCK_REGION_1_LOCK_REGION_0;
2566 
2567 	while (lock_regions) {
2568 		code0 = code1 = 0;
2569 		if (lock_regions & BIT(0)) {
2570 			code0 = ADSP2_LOCK_CODE_0;
2571 			code1 = ADSP2_LOCK_CODE_1;
2572 		}
2573 		if (lock_regions & BIT(1)) {
2574 			code0 |= ADSP2_LOCK_CODE_0 << ADSP2_LOCK_REGION_SHIFT;
2575 			code1 |= ADSP2_LOCK_CODE_1 << ADSP2_LOCK_REGION_SHIFT;
2576 		}
2577 		regmap_write(regmap, lock_reg, code0);
2578 		regmap_write(regmap, lock_reg, code1);
2579 		lock_regions >>= 2;
2580 		lock_reg += 2;
2581 	}
2582 
2583 	return 0;
2584 }
2585 
2586 static int cs_dsp_adsp2_enable_memory(struct cs_dsp *dsp)
2587 {
2588 	return regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
2589 				  ADSP2_MEM_ENA, ADSP2_MEM_ENA);
2590 }
2591 
2592 static void cs_dsp_adsp2_disable_memory(struct cs_dsp *dsp)
2593 {
2594 	regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
2595 			   ADSP2_MEM_ENA, 0);
2596 }
2597 
2598 static void cs_dsp_adsp2_disable_core(struct cs_dsp *dsp)
2599 {
2600 	regmap_write(dsp->regmap, dsp->base + ADSP2_RDMA_CONFIG_1, 0);
2601 	regmap_write(dsp->regmap, dsp->base + ADSP2_WDMA_CONFIG_1, 0);
2602 	regmap_write(dsp->regmap, dsp->base + ADSP2_WDMA_CONFIG_2, 0);
2603 
2604 	regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
2605 			   ADSP2_SYS_ENA, 0);
2606 }
2607 
2608 static void cs_dsp_adsp2v2_disable_core(struct cs_dsp *dsp)
2609 {
2610 	regmap_write(dsp->regmap, dsp->base + ADSP2_RDMA_CONFIG_1, 0);
2611 	regmap_write(dsp->regmap, dsp->base + ADSP2_WDMA_CONFIG_1, 0);
2612 	regmap_write(dsp->regmap, dsp->base + ADSP2V2_WDMA_CONFIG_2, 0);
2613 }
2614 
2615 static int cs_dsp_halo_configure_mpu(struct cs_dsp *dsp, unsigned int lock_regions)
2616 {
2617 	struct reg_sequence config[] = {
2618 		{ dsp->base + HALO_MPU_LOCK_CONFIG,     0x5555 },
2619 		{ dsp->base + HALO_MPU_LOCK_CONFIG,     0xAAAA },
2620 		{ dsp->base + HALO_MPU_XMEM_ACCESS_0,   0xFFFFFFFF },
2621 		{ dsp->base + HALO_MPU_YMEM_ACCESS_0,   0xFFFFFFFF },
2622 		{ dsp->base + HALO_MPU_WINDOW_ACCESS_0, lock_regions },
2623 		{ dsp->base + HALO_MPU_XREG_ACCESS_0,   lock_regions },
2624 		{ dsp->base + HALO_MPU_YREG_ACCESS_0,   lock_regions },
2625 		{ dsp->base + HALO_MPU_XMEM_ACCESS_1,   0xFFFFFFFF },
2626 		{ dsp->base + HALO_MPU_YMEM_ACCESS_1,   0xFFFFFFFF },
2627 		{ dsp->base + HALO_MPU_WINDOW_ACCESS_1, lock_regions },
2628 		{ dsp->base + HALO_MPU_XREG_ACCESS_1,   lock_regions },
2629 		{ dsp->base + HALO_MPU_YREG_ACCESS_1,   lock_regions },
2630 		{ dsp->base + HALO_MPU_XMEM_ACCESS_2,   0xFFFFFFFF },
2631 		{ dsp->base + HALO_MPU_YMEM_ACCESS_2,   0xFFFFFFFF },
2632 		{ dsp->base + HALO_MPU_WINDOW_ACCESS_2, lock_regions },
2633 		{ dsp->base + HALO_MPU_XREG_ACCESS_2,   lock_regions },
2634 		{ dsp->base + HALO_MPU_YREG_ACCESS_2,   lock_regions },
2635 		{ dsp->base + HALO_MPU_XMEM_ACCESS_3,   0xFFFFFFFF },
2636 		{ dsp->base + HALO_MPU_YMEM_ACCESS_3,   0xFFFFFFFF },
2637 		{ dsp->base + HALO_MPU_WINDOW_ACCESS_3, lock_regions },
2638 		{ dsp->base + HALO_MPU_XREG_ACCESS_3,   lock_regions },
2639 		{ dsp->base + HALO_MPU_YREG_ACCESS_3,   lock_regions },
2640 		{ dsp->base + HALO_MPU_LOCK_CONFIG,     0 },
2641 	};
2642 
2643 	return regmap_multi_reg_write(dsp->regmap, config, ARRAY_SIZE(config));
2644 }
2645 
2646 /**
2647  * cs_dsp_set_dspclk() - Applies the given frequency to the given cs_dsp
2648  * @dsp: pointer to DSP structure
2649  * @freq: clock rate to set
2650  *
2651  * This is only for use on ADSP2 cores.
2652  *
2653  * Return: Zero for success, a negative number on error.
2654  */
2655 int cs_dsp_set_dspclk(struct cs_dsp *dsp, unsigned int freq)
2656 {
2657 	int ret;
2658 
2659 	ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CLOCKING,
2660 				 ADSP2_CLK_SEL_MASK,
2661 				 freq << ADSP2_CLK_SEL_SHIFT);
2662 	if (ret)
2663 		cs_dsp_err(dsp, "Failed to set clock rate: %d\n", ret);
2664 
2665 	return ret;
2666 }
2667 EXPORT_SYMBOL_NS_GPL(cs_dsp_set_dspclk, "FW_CS_DSP");
2668 
2669 static void cs_dsp_stop_watchdog(struct cs_dsp *dsp)
2670 {
2671 	regmap_update_bits(dsp->regmap, dsp->base + ADSP2_WATCHDOG,
2672 			   ADSP2_WDT_ENA_MASK, 0);
2673 }
2674 
2675 static void cs_dsp_halo_stop_watchdog(struct cs_dsp *dsp)
2676 {
2677 	regmap_update_bits(dsp->regmap, dsp->base + HALO_WDT_CONTROL,
2678 			   HALO_WDT_EN_MASK, 0);
2679 }
2680 
2681 /**
2682  * cs_dsp_power_up() - Downloads firmware to the DSP
2683  * @dsp: pointer to DSP structure
2684  * @wmfw_firmware: the firmware to be sent
2685  * @wmfw_filename: file name of firmware to be sent
2686  * @coeff_firmware: the coefficient data to be sent
2687  * @coeff_filename: file name of coefficient to data be sent
2688  * @fw_name: the user-friendly firmware name
2689  *
2690  * This function is used on ADSP2 and Halo DSP cores, it powers-up the DSP core
2691  * and downloads the firmware but does not start the firmware running. The
2692  * cs_dsp booted flag will be set once completed and if the core has a low-power
2693  * memory retention mode it will be put into this state after the firmware is
2694  * downloaded.
2695  *
2696  * Return: Zero for success, a negative number on error.
2697  */
2698 int cs_dsp_power_up(struct cs_dsp *dsp,
2699 		    const struct firmware *wmfw_firmware, const char *wmfw_filename,
2700 		    const struct firmware *coeff_firmware, const char *coeff_filename,
2701 		    const char *fw_name)
2702 {
2703 	int ret;
2704 
2705 	mutex_lock(&dsp->pwr_lock);
2706 
2707 	dsp->fw_name = fw_name;
2708 
2709 	if (dsp->ops->enable_memory) {
2710 		ret = dsp->ops->enable_memory(dsp);
2711 		if (ret != 0)
2712 			goto err_mutex;
2713 	}
2714 
2715 	if (dsp->ops->enable_core) {
2716 		ret = dsp->ops->enable_core(dsp);
2717 		if (ret != 0)
2718 			goto err_mem;
2719 	}
2720 
2721 	ret = cs_dsp_load(dsp, wmfw_firmware, wmfw_filename);
2722 	if (ret != 0)
2723 		goto err_ena;
2724 
2725 	ret = dsp->ops->setup_algs(dsp);
2726 	if (ret != 0)
2727 		goto err_ena;
2728 
2729 	ret = cs_dsp_load_coeff(dsp, coeff_firmware, coeff_filename);
2730 	if (ret != 0)
2731 		goto err_ena;
2732 
2733 	/* Initialize caches for enabled and unset controls */
2734 	ret = cs_dsp_coeff_init_control_caches(dsp);
2735 	if (ret != 0)
2736 		goto err_ena;
2737 
2738 	if (dsp->ops->disable_core)
2739 		dsp->ops->disable_core(dsp);
2740 
2741 	dsp->booted = true;
2742 
2743 	mutex_unlock(&dsp->pwr_lock);
2744 
2745 	return 0;
2746 err_ena:
2747 	if (dsp->ops->disable_core)
2748 		dsp->ops->disable_core(dsp);
2749 err_mem:
2750 	if (dsp->ops->disable_memory)
2751 		dsp->ops->disable_memory(dsp);
2752 err_mutex:
2753 	mutex_unlock(&dsp->pwr_lock);
2754 
2755 	return ret;
2756 }
2757 EXPORT_SYMBOL_NS_GPL(cs_dsp_power_up, "FW_CS_DSP");
2758 
2759 /**
2760  * cs_dsp_power_down() - Powers-down the DSP
2761  * @dsp: pointer to DSP structure
2762  *
2763  * cs_dsp_stop() must have been called before this function. The core will be
2764  * fully powered down and so the memory will not be retained.
2765  */
2766 void cs_dsp_power_down(struct cs_dsp *dsp)
2767 {
2768 	struct cs_dsp_coeff_ctl *ctl;
2769 
2770 	mutex_lock(&dsp->pwr_lock);
2771 
2772 	cs_dsp_debugfs_clear(dsp);
2773 
2774 	dsp->fw_id = 0;
2775 	dsp->fw_id_version = 0;
2776 
2777 	dsp->booted = false;
2778 
2779 	if (dsp->ops->disable_memory)
2780 		dsp->ops->disable_memory(dsp);
2781 
2782 	list_for_each_entry(ctl, &dsp->ctl_list, list)
2783 		ctl->enabled = 0;
2784 
2785 	cs_dsp_free_alg_regions(dsp);
2786 
2787 	mutex_unlock(&dsp->pwr_lock);
2788 
2789 	cs_dsp_dbg(dsp, "Shutdown complete\n");
2790 }
2791 EXPORT_SYMBOL_NS_GPL(cs_dsp_power_down, "FW_CS_DSP");
2792 
2793 static int cs_dsp_adsp2_start_core(struct cs_dsp *dsp)
2794 {
2795 	return regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
2796 				  ADSP2_CORE_ENA | ADSP2_START,
2797 				  ADSP2_CORE_ENA | ADSP2_START);
2798 }
2799 
2800 static void cs_dsp_adsp2_stop_core(struct cs_dsp *dsp)
2801 {
2802 	regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
2803 			   ADSP2_CORE_ENA | ADSP2_START, 0);
2804 }
2805 
2806 /**
2807  * cs_dsp_run() - Starts the firmware running
2808  * @dsp: pointer to DSP structure
2809  *
2810  * cs_dsp_power_up() must have previously been called successfully.
2811  *
2812  * Return: Zero for success, a negative number on error.
2813  */
2814 int cs_dsp_run(struct cs_dsp *dsp)
2815 {
2816 	int ret;
2817 
2818 	mutex_lock(&dsp->pwr_lock);
2819 
2820 	if (!dsp->booted) {
2821 		ret = -EIO;
2822 		goto err;
2823 	}
2824 
2825 	if (dsp->ops->enable_core) {
2826 		ret = dsp->ops->enable_core(dsp);
2827 		if (ret != 0)
2828 			goto err;
2829 	}
2830 
2831 	if (dsp->client_ops->pre_run) {
2832 		ret = dsp->client_ops->pre_run(dsp);
2833 		if (ret)
2834 			goto err;
2835 	}
2836 
2837 	/* Sync set controls */
2838 	ret = cs_dsp_coeff_sync_controls(dsp);
2839 	if (ret != 0)
2840 		goto err;
2841 
2842 	if (dsp->ops->lock_memory) {
2843 		ret = dsp->ops->lock_memory(dsp, dsp->lock_regions);
2844 		if (ret != 0) {
2845 			cs_dsp_err(dsp, "Error configuring MPU: %d\n", ret);
2846 			goto err;
2847 		}
2848 	}
2849 
2850 	if (dsp->ops->start_core) {
2851 		ret = dsp->ops->start_core(dsp);
2852 		if (ret != 0)
2853 			goto err;
2854 	}
2855 
2856 	dsp->running = true;
2857 
2858 	if (dsp->client_ops->post_run) {
2859 		ret = dsp->client_ops->post_run(dsp);
2860 		if (ret)
2861 			goto err;
2862 	}
2863 
2864 	mutex_unlock(&dsp->pwr_lock);
2865 
2866 	return 0;
2867 
2868 err:
2869 	if (dsp->ops->stop_core)
2870 		dsp->ops->stop_core(dsp);
2871 	if (dsp->ops->disable_core)
2872 		dsp->ops->disable_core(dsp);
2873 	mutex_unlock(&dsp->pwr_lock);
2874 
2875 	return ret;
2876 }
2877 EXPORT_SYMBOL_NS_GPL(cs_dsp_run, "FW_CS_DSP");
2878 
2879 /**
2880  * cs_dsp_stop() - Stops the firmware
2881  * @dsp: pointer to DSP structure
2882  *
2883  * Memory will not be disabled so firmware will remain loaded.
2884  */
2885 void cs_dsp_stop(struct cs_dsp *dsp)
2886 {
2887 	/* Tell the firmware to cleanup */
2888 	cs_dsp_signal_event_controls(dsp, CS_DSP_FW_EVENT_SHUTDOWN);
2889 
2890 	if (dsp->ops->stop_watchdog)
2891 		dsp->ops->stop_watchdog(dsp);
2892 
2893 	/* Log firmware state, it can be useful for analysis */
2894 	if (dsp->ops->show_fw_status)
2895 		dsp->ops->show_fw_status(dsp);
2896 
2897 	mutex_lock(&dsp->pwr_lock);
2898 
2899 	if (dsp->client_ops->pre_stop)
2900 		dsp->client_ops->pre_stop(dsp);
2901 
2902 	dsp->running = false;
2903 
2904 	if (dsp->ops->stop_core)
2905 		dsp->ops->stop_core(dsp);
2906 	if (dsp->ops->disable_core)
2907 		dsp->ops->disable_core(dsp);
2908 
2909 	if (dsp->client_ops->post_stop)
2910 		dsp->client_ops->post_stop(dsp);
2911 
2912 	mutex_unlock(&dsp->pwr_lock);
2913 
2914 	cs_dsp_dbg(dsp, "Execution stopped\n");
2915 }
2916 EXPORT_SYMBOL_NS_GPL(cs_dsp_stop, "FW_CS_DSP");
2917 
2918 static int cs_dsp_halo_start_core(struct cs_dsp *dsp)
2919 {
2920 	int ret;
2921 
2922 	ret = regmap_update_bits(dsp->regmap, dsp->base + HALO_CCM_CORE_CONTROL,
2923 				 HALO_CORE_RESET | HALO_CORE_EN,
2924 				 HALO_CORE_RESET | HALO_CORE_EN);
2925 	if (ret)
2926 		return ret;
2927 
2928 	return regmap_update_bits(dsp->regmap, dsp->base + HALO_CCM_CORE_CONTROL,
2929 				  HALO_CORE_RESET, 0);
2930 }
2931 
2932 static void cs_dsp_halo_stop_core(struct cs_dsp *dsp)
2933 {
2934 	regmap_update_bits(dsp->regmap, dsp->base + HALO_CCM_CORE_CONTROL,
2935 			   HALO_CORE_EN, 0);
2936 
2937 	/* reset halo core with CORE_SOFT_RESET */
2938 	regmap_update_bits(dsp->regmap, dsp->base + HALO_CORE_SOFT_RESET,
2939 			   HALO_CORE_SOFT_RESET_MASK, 1);
2940 }
2941 
2942 /**
2943  * cs_dsp_adsp2_init() - Initialise a cs_dsp structure representing a ADSP2 core
2944  * @dsp: pointer to DSP structure
2945  *
2946  * Return: Zero for success, a negative number on error.
2947  */
2948 int cs_dsp_adsp2_init(struct cs_dsp *dsp)
2949 {
2950 	int ret;
2951 
2952 	switch (dsp->rev) {
2953 	case 0:
2954 		/*
2955 		 * Disable the DSP memory by default when in reset for a small
2956 		 * power saving.
2957 		 */
2958 		ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
2959 					 ADSP2_MEM_ENA, 0);
2960 		if (ret) {
2961 			cs_dsp_err(dsp,
2962 				   "Failed to clear memory retention: %d\n", ret);
2963 			return ret;
2964 		}
2965 
2966 		dsp->ops = &cs_dsp_adsp2_ops[0];
2967 		break;
2968 	case 1:
2969 		dsp->ops = &cs_dsp_adsp2_ops[1];
2970 		break;
2971 	default:
2972 		dsp->ops = &cs_dsp_adsp2_ops[2];
2973 		break;
2974 	}
2975 
2976 	return cs_dsp_common_init(dsp);
2977 }
2978 EXPORT_SYMBOL_NS_GPL(cs_dsp_adsp2_init, "FW_CS_DSP");
2979 
2980 /**
2981  * cs_dsp_halo_init() - Initialise a cs_dsp structure representing a HALO Core DSP
2982  * @dsp: pointer to DSP structure
2983  *
2984  * Return: Zero for success, a negative number on error.
2985  */
2986 int cs_dsp_halo_init(struct cs_dsp *dsp)
2987 {
2988 	if (dsp->no_core_startstop)
2989 		dsp->ops = &cs_dsp_halo_ao_ops;
2990 	else
2991 		dsp->ops = &cs_dsp_halo_ops;
2992 
2993 	return cs_dsp_common_init(dsp);
2994 }
2995 EXPORT_SYMBOL_NS_GPL(cs_dsp_halo_init, "FW_CS_DSP");
2996 
2997 /**
2998  * cs_dsp_remove() - Clean a cs_dsp before deletion
2999  * @dsp: pointer to DSP structure
3000  */
3001 void cs_dsp_remove(struct cs_dsp *dsp)
3002 {
3003 	struct cs_dsp_coeff_ctl *ctl;
3004 
3005 	while (!list_empty(&dsp->ctl_list)) {
3006 		ctl = list_first_entry(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
3007 
3008 		if (dsp->client_ops->control_remove)
3009 			dsp->client_ops->control_remove(ctl);
3010 
3011 		list_del(&ctl->list);
3012 		cs_dsp_free_ctl_blk(ctl);
3013 	}
3014 }
3015 EXPORT_SYMBOL_NS_GPL(cs_dsp_remove, "FW_CS_DSP");
3016 
3017 /**
3018  * cs_dsp_read_raw_data_block() - Reads a block of data from DSP memory
3019  * @dsp: pointer to DSP structure
3020  * @mem_type: the type of DSP memory containing the data to be read
3021  * @mem_addr: the address of the data within the memory region
3022  * @num_words: the length of the data to read
3023  * @data: a buffer to store the fetched data
3024  *
3025  * If this is used to read unpacked 24-bit memory, each 24-bit DSP word will
3026  * occupy 32-bits in data (MSbyte will be 0). This padding can be removed using
3027  * cs_dsp_remove_padding()
3028  *
3029  * Return: Zero for success, a negative number on error.
3030  */
3031 int cs_dsp_read_raw_data_block(struct cs_dsp *dsp, int mem_type, unsigned int mem_addr,
3032 			       unsigned int num_words, __be32 *data)
3033 {
3034 	struct cs_dsp_region const *mem = cs_dsp_find_region(dsp, mem_type);
3035 	unsigned int reg;
3036 	int ret;
3037 
3038 	lockdep_assert_held(&dsp->pwr_lock);
3039 
3040 	if (!mem)
3041 		return -EINVAL;
3042 
3043 	reg = dsp->ops->region_to_reg(mem, mem_addr);
3044 
3045 	ret = regmap_raw_read(dsp->regmap, reg, data,
3046 			      sizeof(*data) * num_words);
3047 	if (ret < 0)
3048 		return ret;
3049 
3050 	return 0;
3051 }
3052 EXPORT_SYMBOL_NS_GPL(cs_dsp_read_raw_data_block, "FW_CS_DSP");
3053 
3054 /**
3055  * cs_dsp_read_data_word() - Reads a word from DSP memory
3056  * @dsp: pointer to DSP structure
3057  * @mem_type: the type of DSP memory containing the data to be read
3058  * @mem_addr: the address of the data within the memory region
3059  * @data: a buffer to store the fetched data
3060  *
3061  * Return: Zero for success, a negative number on error.
3062  */
3063 int cs_dsp_read_data_word(struct cs_dsp *dsp, int mem_type, unsigned int mem_addr, u32 *data)
3064 {
3065 	__be32 raw;
3066 	int ret;
3067 
3068 	ret = cs_dsp_read_raw_data_block(dsp, mem_type, mem_addr, 1, &raw);
3069 	if (ret < 0)
3070 		return ret;
3071 
3072 	*data = be32_to_cpu(raw) & 0x00ffffffu;
3073 
3074 	return 0;
3075 }
3076 EXPORT_SYMBOL_NS_GPL(cs_dsp_read_data_word, "FW_CS_DSP");
3077 
3078 /**
3079  * cs_dsp_write_data_word() - Writes a word to DSP memory
3080  * @dsp: pointer to DSP structure
3081  * @mem_type: the type of DSP memory containing the data to be written
3082  * @mem_addr: the address of the data within the memory region
3083  * @data: the data to be written
3084  *
3085  * Return: Zero for success, a negative number on error.
3086  */
3087 int cs_dsp_write_data_word(struct cs_dsp *dsp, int mem_type, unsigned int mem_addr, u32 data)
3088 {
3089 	struct cs_dsp_region const *mem = cs_dsp_find_region(dsp, mem_type);
3090 	__be32 val = cpu_to_be32(data & 0x00ffffffu);
3091 	unsigned int reg;
3092 
3093 	lockdep_assert_held(&dsp->pwr_lock);
3094 
3095 	if (!mem)
3096 		return -EINVAL;
3097 
3098 	reg = dsp->ops->region_to_reg(mem, mem_addr);
3099 
3100 	return regmap_raw_write(dsp->regmap, reg, &val, sizeof(val));
3101 }
3102 EXPORT_SYMBOL_NS_GPL(cs_dsp_write_data_word, "FW_CS_DSP");
3103 
3104 /**
3105  * cs_dsp_remove_padding() - Convert unpacked words to packed bytes
3106  * @buf: buffer containing DSP words read from DSP memory
3107  * @nwords: number of words to convert
3108  *
3109  * DSP words from the register map have pad bytes and the data bytes
3110  * are in swapped order. This swaps to the native endian order and
3111  * strips the pad bytes.
3112  */
3113 void cs_dsp_remove_padding(u32 *buf, int nwords)
3114 {
3115 	const __be32 *pack_in = (__be32 *)buf;
3116 	u8 *pack_out = (u8 *)buf;
3117 	int i;
3118 
3119 	for (i = 0; i < nwords; i++) {
3120 		u32 word = be32_to_cpu(*pack_in++);
3121 		*pack_out++ = (u8)word;
3122 		*pack_out++ = (u8)(word >> 8);
3123 		*pack_out++ = (u8)(word >> 16);
3124 	}
3125 }
3126 EXPORT_SYMBOL_NS_GPL(cs_dsp_remove_padding, "FW_CS_DSP");
3127 
3128 /**
3129  * cs_dsp_adsp2_bus_error() - Handle a DSP bus error interrupt
3130  * @dsp: pointer to DSP structure
3131  *
3132  * The firmware and DSP state will be logged for future analysis.
3133  */
3134 void cs_dsp_adsp2_bus_error(struct cs_dsp *dsp)
3135 {
3136 	unsigned int val;
3137 	struct regmap *regmap = dsp->regmap;
3138 	int ret = 0;
3139 
3140 	mutex_lock(&dsp->pwr_lock);
3141 
3142 	ret = regmap_read(regmap, dsp->base + ADSP2_LOCK_REGION_CTRL, &val);
3143 	if (ret) {
3144 		cs_dsp_err(dsp,
3145 			   "Failed to read Region Lock Ctrl register: %d\n", ret);
3146 		goto error;
3147 	}
3148 
3149 	if (val & ADSP2_WDT_TIMEOUT_STS_MASK) {
3150 		cs_dsp_err(dsp, "watchdog timeout error\n");
3151 		dsp->ops->stop_watchdog(dsp);
3152 		if (dsp->client_ops->watchdog_expired)
3153 			dsp->client_ops->watchdog_expired(dsp);
3154 	}
3155 
3156 	if (val & (ADSP2_ADDR_ERR_MASK | ADSP2_REGION_LOCK_ERR_MASK)) {
3157 		if (val & ADSP2_ADDR_ERR_MASK)
3158 			cs_dsp_err(dsp, "bus error: address error\n");
3159 		else
3160 			cs_dsp_err(dsp, "bus error: region lock error\n");
3161 
3162 		ret = regmap_read(regmap, dsp->base + ADSP2_BUS_ERR_ADDR, &val);
3163 		if (ret) {
3164 			cs_dsp_err(dsp,
3165 				   "Failed to read Bus Err Addr register: %d\n",
3166 				   ret);
3167 			goto error;
3168 		}
3169 
3170 		cs_dsp_err(dsp, "bus error address = 0x%x\n",
3171 			   val & ADSP2_BUS_ERR_ADDR_MASK);
3172 
3173 		ret = regmap_read(regmap,
3174 				  dsp->base + ADSP2_PMEM_ERR_ADDR_XMEM_ERR_ADDR,
3175 				  &val);
3176 		if (ret) {
3177 			cs_dsp_err(dsp,
3178 				   "Failed to read Pmem Xmem Err Addr register: %d\n",
3179 				   ret);
3180 			goto error;
3181 		}
3182 
3183 		cs_dsp_err(dsp, "xmem error address = 0x%x\n",
3184 			   val & ADSP2_XMEM_ERR_ADDR_MASK);
3185 		cs_dsp_err(dsp, "pmem error address = 0x%x\n",
3186 			   (val & ADSP2_PMEM_ERR_ADDR_MASK) >>
3187 			   ADSP2_PMEM_ERR_ADDR_SHIFT);
3188 	}
3189 
3190 	regmap_update_bits(regmap, dsp->base + ADSP2_LOCK_REGION_CTRL,
3191 			   ADSP2_CTRL_ERR_EINT, ADSP2_CTRL_ERR_EINT);
3192 
3193 error:
3194 	mutex_unlock(&dsp->pwr_lock);
3195 }
3196 EXPORT_SYMBOL_NS_GPL(cs_dsp_adsp2_bus_error, "FW_CS_DSP");
3197 
3198 /**
3199  * cs_dsp_halo_bus_error() - Handle a DSP bus error interrupt
3200  * @dsp: pointer to DSP structure
3201  *
3202  * The firmware and DSP state will be logged for future analysis.
3203  */
3204 void cs_dsp_halo_bus_error(struct cs_dsp *dsp)
3205 {
3206 	struct regmap *regmap = dsp->regmap;
3207 	unsigned int fault[6];
3208 	struct reg_sequence clear[] = {
3209 		{ dsp->base + HALO_MPU_XM_VIO_STATUS,     0x0 },
3210 		{ dsp->base + HALO_MPU_YM_VIO_STATUS,     0x0 },
3211 		{ dsp->base + HALO_MPU_PM_VIO_STATUS,     0x0 },
3212 	};
3213 	int ret;
3214 
3215 	mutex_lock(&dsp->pwr_lock);
3216 
3217 	ret = regmap_read(regmap, dsp->base_sysinfo + HALO_AHBM_WINDOW_DEBUG_1,
3218 			  fault);
3219 	if (ret) {
3220 		cs_dsp_warn(dsp, "Failed to read AHB DEBUG_1: %d\n", ret);
3221 		goto exit_unlock;
3222 	}
3223 
3224 	cs_dsp_warn(dsp, "AHB: STATUS: 0x%x ADDR: 0x%x\n",
3225 		    *fault & HALO_AHBM_FLAGS_ERR_MASK,
3226 		    (*fault & HALO_AHBM_CORE_ERR_ADDR_MASK) >>
3227 		    HALO_AHBM_CORE_ERR_ADDR_SHIFT);
3228 
3229 	ret = regmap_read(regmap, dsp->base_sysinfo + HALO_AHBM_WINDOW_DEBUG_0,
3230 			  fault);
3231 	if (ret) {
3232 		cs_dsp_warn(dsp, "Failed to read AHB DEBUG_0: %d\n", ret);
3233 		goto exit_unlock;
3234 	}
3235 
3236 	cs_dsp_warn(dsp, "AHB: SYS_ADDR: 0x%x\n", *fault);
3237 
3238 	ret = regmap_bulk_read(regmap, dsp->base + HALO_MPU_XM_VIO_ADDR,
3239 			       fault, ARRAY_SIZE(fault));
3240 	if (ret) {
3241 		cs_dsp_warn(dsp, "Failed to read MPU fault info: %d\n", ret);
3242 		goto exit_unlock;
3243 	}
3244 
3245 	cs_dsp_warn(dsp, "XM: STATUS:0x%x ADDR:0x%x\n", fault[1], fault[0]);
3246 	cs_dsp_warn(dsp, "YM: STATUS:0x%x ADDR:0x%x\n", fault[3], fault[2]);
3247 	cs_dsp_warn(dsp, "PM: STATUS:0x%x ADDR:0x%x\n", fault[5], fault[4]);
3248 
3249 	ret = regmap_multi_reg_write(dsp->regmap, clear, ARRAY_SIZE(clear));
3250 	if (ret)
3251 		cs_dsp_warn(dsp, "Failed to clear MPU status: %d\n", ret);
3252 
3253 exit_unlock:
3254 	mutex_unlock(&dsp->pwr_lock);
3255 }
3256 EXPORT_SYMBOL_NS_GPL(cs_dsp_halo_bus_error, "FW_CS_DSP");
3257 
3258 /**
3259  * cs_dsp_halo_wdt_expire() - Handle DSP watchdog expiry
3260  * @dsp: pointer to DSP structure
3261  *
3262  * This is logged for future analysis.
3263  */
3264 void cs_dsp_halo_wdt_expire(struct cs_dsp *dsp)
3265 {
3266 	mutex_lock(&dsp->pwr_lock);
3267 
3268 	cs_dsp_warn(dsp, "WDT Expiry Fault\n");
3269 
3270 	dsp->ops->stop_watchdog(dsp);
3271 	if (dsp->client_ops->watchdog_expired)
3272 		dsp->client_ops->watchdog_expired(dsp);
3273 
3274 	mutex_unlock(&dsp->pwr_lock);
3275 }
3276 EXPORT_SYMBOL_NS_GPL(cs_dsp_halo_wdt_expire, "FW_CS_DSP");
3277 
3278 static const struct cs_dsp_ops cs_dsp_adsp1_ops = {
3279 	.validate_version = cs_dsp_validate_version,
3280 	.parse_sizes = cs_dsp_adsp1_parse_sizes,
3281 	.region_to_reg = cs_dsp_region_to_reg,
3282 };
3283 
3284 static const struct cs_dsp_ops cs_dsp_adsp2_ops[] = {
3285 	{
3286 		.parse_sizes = cs_dsp_adsp2_parse_sizes,
3287 		.validate_version = cs_dsp_validate_version,
3288 		.setup_algs = cs_dsp_adsp2_setup_algs,
3289 		.region_to_reg = cs_dsp_region_to_reg,
3290 
3291 		.show_fw_status = cs_dsp_adsp2_show_fw_status,
3292 
3293 		.enable_memory = cs_dsp_adsp2_enable_memory,
3294 		.disable_memory = cs_dsp_adsp2_disable_memory,
3295 
3296 		.enable_core = cs_dsp_adsp2_enable_core,
3297 		.disable_core = cs_dsp_adsp2_disable_core,
3298 
3299 		.start_core = cs_dsp_adsp2_start_core,
3300 		.stop_core = cs_dsp_adsp2_stop_core,
3301 
3302 	},
3303 	{
3304 		.parse_sizes = cs_dsp_adsp2_parse_sizes,
3305 		.validate_version = cs_dsp_validate_version,
3306 		.setup_algs = cs_dsp_adsp2_setup_algs,
3307 		.region_to_reg = cs_dsp_region_to_reg,
3308 
3309 		.show_fw_status = cs_dsp_adsp2v2_show_fw_status,
3310 
3311 		.enable_memory = cs_dsp_adsp2_enable_memory,
3312 		.disable_memory = cs_dsp_adsp2_disable_memory,
3313 		.lock_memory = cs_dsp_adsp2_lock,
3314 
3315 		.enable_core = cs_dsp_adsp2v2_enable_core,
3316 		.disable_core = cs_dsp_adsp2v2_disable_core,
3317 
3318 		.start_core = cs_dsp_adsp2_start_core,
3319 		.stop_core = cs_dsp_adsp2_stop_core,
3320 	},
3321 	{
3322 		.parse_sizes = cs_dsp_adsp2_parse_sizes,
3323 		.validate_version = cs_dsp_validate_version,
3324 		.setup_algs = cs_dsp_adsp2_setup_algs,
3325 		.region_to_reg = cs_dsp_region_to_reg,
3326 
3327 		.show_fw_status = cs_dsp_adsp2v2_show_fw_status,
3328 		.stop_watchdog = cs_dsp_stop_watchdog,
3329 
3330 		.enable_memory = cs_dsp_adsp2_enable_memory,
3331 		.disable_memory = cs_dsp_adsp2_disable_memory,
3332 		.lock_memory = cs_dsp_adsp2_lock,
3333 
3334 		.enable_core = cs_dsp_adsp2v2_enable_core,
3335 		.disable_core = cs_dsp_adsp2v2_disable_core,
3336 
3337 		.start_core = cs_dsp_adsp2_start_core,
3338 		.stop_core = cs_dsp_adsp2_stop_core,
3339 	},
3340 };
3341 
3342 static const struct cs_dsp_ops cs_dsp_halo_ops = {
3343 	.parse_sizes = cs_dsp_adsp2_parse_sizes,
3344 	.validate_version = cs_dsp_halo_validate_version,
3345 	.setup_algs = cs_dsp_halo_setup_algs,
3346 	.region_to_reg = cs_dsp_halo_region_to_reg,
3347 
3348 	.show_fw_status = cs_dsp_halo_show_fw_status,
3349 	.stop_watchdog = cs_dsp_halo_stop_watchdog,
3350 
3351 	.lock_memory = cs_dsp_halo_configure_mpu,
3352 
3353 	.start_core = cs_dsp_halo_start_core,
3354 	.stop_core = cs_dsp_halo_stop_core,
3355 };
3356 
3357 static const struct cs_dsp_ops cs_dsp_halo_ao_ops = {
3358 	.parse_sizes = cs_dsp_adsp2_parse_sizes,
3359 	.validate_version = cs_dsp_halo_validate_version,
3360 	.setup_algs = cs_dsp_halo_setup_algs,
3361 	.region_to_reg = cs_dsp_halo_region_to_reg,
3362 	.show_fw_status = cs_dsp_halo_show_fw_status,
3363 };
3364 
3365 /**
3366  * cs_dsp_chunk_write() - Format data to a DSP memory chunk
3367  * @ch: Pointer to the chunk structure
3368  * @nbits: Number of bits to write
3369  * @val: Value to write
3370  *
3371  * This function sequentially writes values into the format required for DSP
3372  * memory, it handles both inserting of the padding bytes and converting to
3373  * big endian. Note that data is only committed to the chunk when a whole DSP
3374  * words worth of data is available.
3375  *
3376  * Return: Zero for success, a negative number on error.
3377  */
3378 int cs_dsp_chunk_write(struct cs_dsp_chunk *ch, int nbits, u32 val)
3379 {
3380 	int nwrite, i;
3381 
3382 	nwrite = min(CS_DSP_DATA_WORD_BITS - ch->cachebits, nbits);
3383 
3384 	ch->cache <<= nwrite;
3385 	ch->cache |= val >> (nbits - nwrite);
3386 	ch->cachebits += nwrite;
3387 	nbits -= nwrite;
3388 
3389 	if (ch->cachebits == CS_DSP_DATA_WORD_BITS) {
3390 		if (cs_dsp_chunk_end(ch))
3391 			return -ENOSPC;
3392 
3393 		ch->cache &= 0xFFFFFF;
3394 		for (i = 0; i < sizeof(ch->cache); i++, ch->cache <<= BITS_PER_BYTE)
3395 			*ch->data++ = (ch->cache & 0xFF000000) >> CS_DSP_DATA_WORD_BITS;
3396 
3397 		ch->bytes += sizeof(ch->cache);
3398 		ch->cachebits = 0;
3399 	}
3400 
3401 	if (nbits)
3402 		return cs_dsp_chunk_write(ch, nbits, val);
3403 
3404 	return 0;
3405 }
3406 EXPORT_SYMBOL_NS_GPL(cs_dsp_chunk_write, "FW_CS_DSP");
3407 
3408 /**
3409  * cs_dsp_chunk_flush() - Pad remaining data with zero and commit to chunk
3410  * @ch: Pointer to the chunk structure
3411  *
3412  * As cs_dsp_chunk_write only writes data when a whole DSP word is ready to
3413  * be written out it is possible that some data will remain in the cache, this
3414  * function will pad that data with zeros upto a whole DSP word and write out.
3415  *
3416  * Return: Zero for success, a negative number on error.
3417  */
3418 int cs_dsp_chunk_flush(struct cs_dsp_chunk *ch)
3419 {
3420 	if (!ch->cachebits)
3421 		return 0;
3422 
3423 	return cs_dsp_chunk_write(ch, CS_DSP_DATA_WORD_BITS - ch->cachebits, 0);
3424 }
3425 EXPORT_SYMBOL_NS_GPL(cs_dsp_chunk_flush, "FW_CS_DSP");
3426 
3427 /**
3428  * cs_dsp_chunk_read() - Parse data from a DSP memory chunk
3429  * @ch: Pointer to the chunk structure
3430  * @nbits: Number of bits to read
3431  *
3432  * This function sequentially reads values from a DSP memory formatted buffer,
3433  * it handles both removing of the padding bytes and converting from big endian.
3434  *
3435  * Return: A negative number is returned on error, otherwise the read value.
3436  */
3437 int cs_dsp_chunk_read(struct cs_dsp_chunk *ch, int nbits)
3438 {
3439 	int nread, i;
3440 	u32 result;
3441 
3442 	if (!ch->cachebits) {
3443 		if (cs_dsp_chunk_end(ch))
3444 			return -ENOSPC;
3445 
3446 		ch->cache = 0;
3447 		ch->cachebits = CS_DSP_DATA_WORD_BITS;
3448 
3449 		for (i = 0; i < sizeof(ch->cache); i++, ch->cache <<= BITS_PER_BYTE)
3450 			ch->cache |= *ch->data++;
3451 
3452 		ch->bytes += sizeof(ch->cache);
3453 	}
3454 
3455 	nread = min(ch->cachebits, nbits);
3456 	nbits -= nread;
3457 
3458 	result = ch->cache >> ((sizeof(ch->cache) * BITS_PER_BYTE) - nread);
3459 	ch->cache <<= nread;
3460 	ch->cachebits -= nread;
3461 
3462 	if (nbits)
3463 		result = (result << nbits) | cs_dsp_chunk_read(ch, nbits);
3464 
3465 	return result;
3466 }
3467 EXPORT_SYMBOL_NS_GPL(cs_dsp_chunk_read, "FW_CS_DSP");
3468 
3469 
3470 struct cs_dsp_wseq_op {
3471 	struct list_head list;
3472 	u32 address;
3473 	u32 data;
3474 	u16 offset;
3475 	u8 operation;
3476 };
3477 
3478 static void cs_dsp_wseq_clear(struct cs_dsp *dsp, struct cs_dsp_wseq *wseq)
3479 {
3480 	struct cs_dsp_wseq_op *op, *op_tmp;
3481 
3482 	list_for_each_entry_safe(op, op_tmp, &wseq->ops, list) {
3483 		list_del(&op->list);
3484 		devm_kfree(dsp->dev, op);
3485 	}
3486 }
3487 
3488 static int cs_dsp_populate_wseq(struct cs_dsp *dsp, struct cs_dsp_wseq *wseq)
3489 {
3490 	struct cs_dsp_wseq_op *op = NULL;
3491 	struct cs_dsp_chunk chunk;
3492 	u8 *words;
3493 	int ret;
3494 
3495 	if (!wseq->ctl) {
3496 		cs_dsp_err(dsp, "No control for write sequence\n");
3497 		return -EINVAL;
3498 	}
3499 
3500 	words = kzalloc(wseq->ctl->len, GFP_KERNEL);
3501 	if (!words)
3502 		return -ENOMEM;
3503 
3504 	ret = cs_dsp_coeff_read_ctrl(wseq->ctl, 0, words, wseq->ctl->len);
3505 	if (ret) {
3506 		cs_dsp_err(dsp, "Failed to read %s: %d\n", wseq->ctl->subname, ret);
3507 		goto err_free;
3508 	}
3509 
3510 	INIT_LIST_HEAD(&wseq->ops);
3511 
3512 	chunk = cs_dsp_chunk(words, wseq->ctl->len);
3513 
3514 	while (!cs_dsp_chunk_end(&chunk)) {
3515 		op = devm_kzalloc(dsp->dev, sizeof(*op), GFP_KERNEL);
3516 		if (!op) {
3517 			ret = -ENOMEM;
3518 			goto err_free;
3519 		}
3520 
3521 		op->offset = cs_dsp_chunk_bytes(&chunk);
3522 		op->operation = cs_dsp_chunk_read(&chunk, 8);
3523 
3524 		switch (op->operation) {
3525 		case CS_DSP_WSEQ_END:
3526 			op->data = WSEQ_END_OF_SCRIPT;
3527 			break;
3528 		case CS_DSP_WSEQ_UNLOCK:
3529 			op->data = cs_dsp_chunk_read(&chunk, 16);
3530 			break;
3531 		case CS_DSP_WSEQ_ADDR8:
3532 			op->address = cs_dsp_chunk_read(&chunk, 8);
3533 			op->data = cs_dsp_chunk_read(&chunk, 32);
3534 			break;
3535 		case CS_DSP_WSEQ_H16:
3536 		case CS_DSP_WSEQ_L16:
3537 			op->address = cs_dsp_chunk_read(&chunk, 24);
3538 			op->data = cs_dsp_chunk_read(&chunk, 16);
3539 			break;
3540 		case CS_DSP_WSEQ_FULL:
3541 			op->address = cs_dsp_chunk_read(&chunk, 32);
3542 			op->data = cs_dsp_chunk_read(&chunk, 32);
3543 			break;
3544 		default:
3545 			ret = -EINVAL;
3546 			cs_dsp_err(dsp, "Unsupported op: %X\n", op->operation);
3547 			devm_kfree(dsp->dev, op);
3548 			goto err_free;
3549 		}
3550 
3551 		list_add_tail(&op->list, &wseq->ops);
3552 
3553 		if (op->operation == CS_DSP_WSEQ_END)
3554 			break;
3555 	}
3556 
3557 	if (op && op->operation != CS_DSP_WSEQ_END) {
3558 		cs_dsp_err(dsp, "%s missing end terminator\n", wseq->ctl->subname);
3559 		ret = -ENOENT;
3560 	}
3561 
3562 err_free:
3563 	kfree(words);
3564 
3565 	return ret;
3566 }
3567 
3568 /**
3569  * cs_dsp_wseq_init() - Initialize write sequences contained within the loaded DSP firmware
3570  * @dsp: Pointer to DSP structure
3571  * @wseqs: List of write sequences to initialize
3572  * @num_wseqs: Number of write sequences to initialize
3573  *
3574  * Return: Zero for success, a negative number on error.
3575  */
3576 int cs_dsp_wseq_init(struct cs_dsp *dsp, struct cs_dsp_wseq *wseqs, unsigned int num_wseqs)
3577 {
3578 	int i, ret;
3579 
3580 	lockdep_assert_held(&dsp->pwr_lock);
3581 
3582 	for (i = 0; i < num_wseqs; i++) {
3583 		ret = cs_dsp_populate_wseq(dsp, &wseqs[i]);
3584 		if (ret) {
3585 			cs_dsp_wseq_clear(dsp, &wseqs[i]);
3586 			return ret;
3587 		}
3588 	}
3589 
3590 	return 0;
3591 }
3592 EXPORT_SYMBOL_NS_GPL(cs_dsp_wseq_init, "FW_CS_DSP");
3593 
3594 static struct cs_dsp_wseq_op *cs_dsp_wseq_find_op(u32 addr, u8 op_code,
3595 						  struct list_head *wseq_ops)
3596 {
3597 	struct cs_dsp_wseq_op *op;
3598 
3599 	list_for_each_entry(op, wseq_ops, list) {
3600 		if (op->operation == op_code && op->address == addr)
3601 			return op;
3602 	}
3603 
3604 	return NULL;
3605 }
3606 
3607 /**
3608  * cs_dsp_wseq_write() - Add or update an entry in a write sequence
3609  * @dsp: Pointer to a DSP structure
3610  * @wseq: Write sequence to write to
3611  * @addr: Address of the register to be written to
3612  * @data: Data to be written
3613  * @op_code: The type of operation of the new entry
3614  * @update: If true, searches for the first entry in the write sequence with
3615  * the same address and op_code, and replaces it. If false, creates a new entry
3616  * at the tail
3617  *
3618  * This function formats register address and value pairs into the format
3619  * required for write sequence entries, and either updates or adds the
3620  * new entry into the write sequence.
3621  *
3622  * If update is set to true and no matching entry is found, it will add a new entry.
3623  *
3624  * Return: Zero for success, a negative number on error.
3625  */
3626 int cs_dsp_wseq_write(struct cs_dsp *dsp, struct cs_dsp_wseq *wseq,
3627 		      u32 addr, u32 data, u8 op_code, bool update)
3628 {
3629 	struct cs_dsp_wseq_op *op_end, *op_new = NULL;
3630 	u32 words[WSEQ_OP_MAX_WORDS];
3631 	struct cs_dsp_chunk chunk;
3632 	int new_op_size, ret;
3633 
3634 	if (update)
3635 		op_new = cs_dsp_wseq_find_op(addr, op_code, &wseq->ops);
3636 
3637 	/* If entry to update is not found, treat it as a new operation */
3638 	if (!op_new) {
3639 		op_end = cs_dsp_wseq_find_op(0, CS_DSP_WSEQ_END, &wseq->ops);
3640 		if (!op_end) {
3641 			cs_dsp_err(dsp, "Missing terminator for %s\n", wseq->ctl->subname);
3642 			return -EINVAL;
3643 		}
3644 
3645 		op_new = devm_kzalloc(dsp->dev, sizeof(*op_new), GFP_KERNEL);
3646 		if (!op_new)
3647 			return -ENOMEM;
3648 
3649 		op_new->operation = op_code;
3650 		op_new->address = addr;
3651 		op_new->offset = op_end->offset;
3652 		update = false;
3653 	}
3654 
3655 	op_new->data = data;
3656 
3657 	chunk = cs_dsp_chunk(words, sizeof(words));
3658 	cs_dsp_chunk_write(&chunk, 8, op_new->operation);
3659 
3660 	switch (op_code) {
3661 	case CS_DSP_WSEQ_FULL:
3662 		cs_dsp_chunk_write(&chunk, 32, op_new->address);
3663 		cs_dsp_chunk_write(&chunk, 32, op_new->data);
3664 		break;
3665 	case CS_DSP_WSEQ_L16:
3666 	case CS_DSP_WSEQ_H16:
3667 		cs_dsp_chunk_write(&chunk, 24, op_new->address);
3668 		cs_dsp_chunk_write(&chunk, 16, op_new->data);
3669 		break;
3670 	default:
3671 		ret = -EINVAL;
3672 		cs_dsp_err(dsp, "Operation %X not supported\n", op_code);
3673 		goto op_new_free;
3674 	}
3675 
3676 	new_op_size = cs_dsp_chunk_bytes(&chunk);
3677 
3678 	if (!update) {
3679 		if (wseq->ctl->len - op_end->offset < new_op_size) {
3680 			cs_dsp_err(dsp, "Not enough memory in %s for entry\n", wseq->ctl->subname);
3681 			ret = -E2BIG;
3682 			goto op_new_free;
3683 		}
3684 
3685 		op_end->offset += new_op_size;
3686 
3687 		ret = cs_dsp_coeff_write_ctrl(wseq->ctl, op_end->offset / sizeof(u32),
3688 					      &op_end->data, sizeof(u32));
3689 		if (ret)
3690 			goto op_new_free;
3691 
3692 		list_add_tail(&op_new->list, &op_end->list);
3693 	}
3694 
3695 	ret = cs_dsp_coeff_write_ctrl(wseq->ctl, op_new->offset / sizeof(u32),
3696 				      words, new_op_size);
3697 	if (ret)
3698 		goto op_new_free;
3699 
3700 	return 0;
3701 
3702 op_new_free:
3703 	devm_kfree(dsp->dev, op_new);
3704 
3705 	return ret;
3706 }
3707 EXPORT_SYMBOL_NS_GPL(cs_dsp_wseq_write, "FW_CS_DSP");
3708 
3709 /**
3710  * cs_dsp_wseq_multi_write() - Add or update multiple entries in a write sequence
3711  * @dsp: Pointer to a DSP structure
3712  * @wseq: Write sequence to write to
3713  * @reg_seq: List of address-data pairs
3714  * @num_regs: Number of address-data pairs
3715  * @op_code: The types of operations of the new entries
3716  * @update: If true, searches for the first entry in the write sequence with
3717  * the same address and op_code, and replaces it. If false, creates a new entry
3718  * at the tail
3719  *
3720  * This function calls cs_dsp_wseq_write() for multiple address-data pairs.
3721  *
3722  * Return: Zero for success, a negative number on error.
3723  */
3724 int cs_dsp_wseq_multi_write(struct cs_dsp *dsp, struct cs_dsp_wseq *wseq,
3725 			    const struct reg_sequence *reg_seq, int num_regs,
3726 			    u8 op_code, bool update)
3727 {
3728 	int i, ret;
3729 
3730 	for (i = 0; i < num_regs; i++) {
3731 		ret = cs_dsp_wseq_write(dsp, wseq, reg_seq[i].reg,
3732 					reg_seq[i].def, op_code, update);
3733 		if (ret)
3734 			return ret;
3735 	}
3736 
3737 	return 0;
3738 }
3739 EXPORT_SYMBOL_NS_GPL(cs_dsp_wseq_multi_write, "FW_CS_DSP");
3740 
3741 MODULE_DESCRIPTION("Cirrus Logic DSP Support");
3742 MODULE_AUTHOR("Simon Trimmer <simont@opensource.cirrus.com>");
3743 MODULE_LICENSE("GPL v2");
3744