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