Merge branch 'for-next/esr-elx-64-bit' into for-next/core
[linux-2.6-microblaze.git] / drivers / firmware / cirrus / cs_dsp.c
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_GPL(cs_dsp_mem_region_name);
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_GPL(cs_dsp_init_debugfs);
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_GPL(cs_dsp_cleanup_debugfs);
496 #else
497 void cs_dsp_init_debugfs(struct cs_dsp *dsp, struct dentry *debugfs_root)
498 {
499 }
500 EXPORT_SYMBOL_GPL(cs_dsp_init_debugfs);
501
502 void cs_dsp_cleanup_debugfs(struct cs_dsp *dsp)
503 {
504 }
505 EXPORT_SYMBOL_GPL(cs_dsp_cleanup_debugfs);
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_GPL(cs_dsp_coeff_write_acked_control);
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: Zero for success, a negative number on error.
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                 memcpy(ctl->cache + off * sizeof(u32), buf, len);
774
775         ctl->set = 1;
776         if (ctl->enabled && ctl->dsp->running)
777                 ret = cs_dsp_coeff_write_ctrl_raw(ctl, off, buf, len);
778
779         return ret;
780 }
781 EXPORT_SYMBOL_GPL(cs_dsp_coeff_write_ctrl);
782
783 static int cs_dsp_coeff_read_ctrl_raw(struct cs_dsp_coeff_ctl *ctl,
784                                       unsigned int off, void *buf, size_t len)
785 {
786         struct cs_dsp *dsp = ctl->dsp;
787         void *scratch;
788         int ret;
789         unsigned int reg;
790
791         ret = cs_dsp_coeff_base_reg(ctl, &reg, off);
792         if (ret)
793                 return ret;
794
795         scratch = kmalloc(len, GFP_KERNEL | GFP_DMA);
796         if (!scratch)
797                 return -ENOMEM;
798
799         ret = regmap_raw_read(dsp->regmap, reg, scratch, len);
800         if (ret) {
801                 cs_dsp_err(dsp, "Failed to read %zu bytes from %x: %d\n",
802                            len, reg, ret);
803                 kfree(scratch);
804                 return ret;
805         }
806         cs_dsp_dbg(dsp, "Read %zu bytes from %x\n", len, reg);
807
808         memcpy(buf, scratch, len);
809         kfree(scratch);
810
811         return 0;
812 }
813
814 /**
815  * cs_dsp_coeff_read_ctrl() - Reads the given coefficient control into the given buffer
816  * @ctl: pointer to coefficient control
817  * @off: word offset at which data should be read
818  * @buf: the buffer to store to the given control
819  * @len: the length of the buffer in bytes
820  *
821  * Must be called with pwr_lock held.
822  *
823  * Return: Zero for success, a negative number on error.
824  */
825 int cs_dsp_coeff_read_ctrl(struct cs_dsp_coeff_ctl *ctl,
826                            unsigned int off, void *buf, size_t len)
827 {
828         int ret = 0;
829
830         if (!ctl)
831                 return -ENOENT;
832
833         lockdep_assert_held(&ctl->dsp->pwr_lock);
834
835         if (len + off * sizeof(u32) > ctl->len)
836                 return -EINVAL;
837
838         if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) {
839                 if (ctl->enabled && ctl->dsp->running)
840                         return cs_dsp_coeff_read_ctrl_raw(ctl, off, buf, len);
841                 else
842                         return -EPERM;
843         } else {
844                 if (!ctl->flags && ctl->enabled && ctl->dsp->running)
845                         ret = cs_dsp_coeff_read_ctrl_raw(ctl, 0, ctl->cache, ctl->len);
846
847                 if (buf != ctl->cache)
848                         memcpy(buf, ctl->cache + off * sizeof(u32), len);
849         }
850
851         return ret;
852 }
853 EXPORT_SYMBOL_GPL(cs_dsp_coeff_read_ctrl);
854
855 static int cs_dsp_coeff_init_control_caches(struct cs_dsp *dsp)
856 {
857         struct cs_dsp_coeff_ctl *ctl;
858         int ret;
859
860         list_for_each_entry(ctl, &dsp->ctl_list, list) {
861                 if (!ctl->enabled || ctl->set)
862                         continue;
863                 if (ctl->flags & WMFW_CTL_FLAG_VOLATILE)
864                         continue;
865
866                 /*
867                  * For readable controls populate the cache from the DSP memory.
868                  * For non-readable controls the cache was zero-filled when
869                  * created so we don't need to do anything.
870                  */
871                 if (!ctl->flags || (ctl->flags & WMFW_CTL_FLAG_READABLE)) {
872                         ret = cs_dsp_coeff_read_ctrl_raw(ctl, 0, ctl->cache, ctl->len);
873                         if (ret < 0)
874                                 return ret;
875                 }
876         }
877
878         return 0;
879 }
880
881 static int cs_dsp_coeff_sync_controls(struct cs_dsp *dsp)
882 {
883         struct cs_dsp_coeff_ctl *ctl;
884         int ret;
885
886         list_for_each_entry(ctl, &dsp->ctl_list, list) {
887                 if (!ctl->enabled)
888                         continue;
889                 if (ctl->set && !(ctl->flags & WMFW_CTL_FLAG_VOLATILE)) {
890                         ret = cs_dsp_coeff_write_ctrl_raw(ctl, 0, ctl->cache,
891                                                           ctl->len);
892                         if (ret < 0)
893                                 return ret;
894                 }
895         }
896
897         return 0;
898 }
899
900 static void cs_dsp_signal_event_controls(struct cs_dsp *dsp,
901                                          unsigned int event)
902 {
903         struct cs_dsp_coeff_ctl *ctl;
904         int ret;
905
906         list_for_each_entry(ctl, &dsp->ctl_list, list) {
907                 if (ctl->type != WMFW_CTL_TYPE_HOSTEVENT)
908                         continue;
909
910                 if (!ctl->enabled)
911                         continue;
912
913                 ret = cs_dsp_coeff_write_acked_control(ctl, event);
914                 if (ret)
915                         cs_dsp_warn(dsp,
916                                     "Failed to send 0x%x event to alg 0x%x (%d)\n",
917                                     event, ctl->alg_region.alg, ret);
918         }
919 }
920
921 static void cs_dsp_free_ctl_blk(struct cs_dsp_coeff_ctl *ctl)
922 {
923         kfree(ctl->cache);
924         kfree(ctl->subname);
925         kfree(ctl);
926 }
927
928 static int cs_dsp_create_control(struct cs_dsp *dsp,
929                                  const struct cs_dsp_alg_region *alg_region,
930                                  unsigned int offset, unsigned int len,
931                                  const char *subname, unsigned int subname_len,
932                                  unsigned int flags, unsigned int type)
933 {
934         struct cs_dsp_coeff_ctl *ctl;
935         int ret;
936
937         list_for_each_entry(ctl, &dsp->ctl_list, list) {
938                 if (ctl->fw_name == dsp->fw_name &&
939                     ctl->alg_region.alg == alg_region->alg &&
940                     ctl->alg_region.type == alg_region->type) {
941                         if ((!subname && !ctl->subname) ||
942                             (subname && !strncmp(ctl->subname, subname, ctl->subname_len))) {
943                                 if (!ctl->enabled)
944                                         ctl->enabled = 1;
945                                 return 0;
946                         }
947                 }
948         }
949
950         ctl = kzalloc(sizeof(*ctl), GFP_KERNEL);
951         if (!ctl)
952                 return -ENOMEM;
953
954         ctl->fw_name = dsp->fw_name;
955         ctl->alg_region = *alg_region;
956         if (subname && dsp->fw_ver >= 2) {
957                 ctl->subname_len = subname_len;
958                 ctl->subname = kmemdup(subname,
959                                        strlen(subname) + 1, GFP_KERNEL);
960                 if (!ctl->subname) {
961                         ret = -ENOMEM;
962                         goto err_ctl;
963                 }
964         }
965         ctl->enabled = 1;
966         ctl->set = 0;
967         ctl->dsp = dsp;
968
969         ctl->flags = flags;
970         ctl->type = type;
971         ctl->offset = offset;
972         ctl->len = len;
973         ctl->cache = kzalloc(ctl->len, GFP_KERNEL);
974         if (!ctl->cache) {
975                 ret = -ENOMEM;
976                 goto err_ctl_subname;
977         }
978
979         list_add(&ctl->list, &dsp->ctl_list);
980
981         if (dsp->client_ops->control_add) {
982                 ret = dsp->client_ops->control_add(ctl);
983                 if (ret)
984                         goto err_list_del;
985         }
986
987         return 0;
988
989 err_list_del:
990         list_del(&ctl->list);
991         kfree(ctl->cache);
992 err_ctl_subname:
993         kfree(ctl->subname);
994 err_ctl:
995         kfree(ctl);
996
997         return ret;
998 }
999
1000 struct cs_dsp_coeff_parsed_alg {
1001         int id;
1002         const u8 *name;
1003         int name_len;
1004         int ncoeff;
1005 };
1006
1007 struct cs_dsp_coeff_parsed_coeff {
1008         int offset;
1009         int mem_type;
1010         const u8 *name;
1011         int name_len;
1012         unsigned int ctl_type;
1013         int flags;
1014         int len;
1015 };
1016
1017 static int cs_dsp_coeff_parse_string(int bytes, const u8 **pos, const u8 **str)
1018 {
1019         int length;
1020
1021         switch (bytes) {
1022         case 1:
1023                 length = **pos;
1024                 break;
1025         case 2:
1026                 length = le16_to_cpu(*((__le16 *)*pos));
1027                 break;
1028         default:
1029                 return 0;
1030         }
1031
1032         if (str)
1033                 *str = *pos + bytes;
1034
1035         *pos += ((length + bytes) + 3) & ~0x03;
1036
1037         return length;
1038 }
1039
1040 static int cs_dsp_coeff_parse_int(int bytes, const u8 **pos)
1041 {
1042         int val = 0;
1043
1044         switch (bytes) {
1045         case 2:
1046                 val = le16_to_cpu(*((__le16 *)*pos));
1047                 break;
1048         case 4:
1049                 val = le32_to_cpu(*((__le32 *)*pos));
1050                 break;
1051         default:
1052                 break;
1053         }
1054
1055         *pos += bytes;
1056
1057         return val;
1058 }
1059
1060 static inline void cs_dsp_coeff_parse_alg(struct cs_dsp *dsp, const u8 **data,
1061                                           struct cs_dsp_coeff_parsed_alg *blk)
1062 {
1063         const struct wmfw_adsp_alg_data *raw;
1064
1065         switch (dsp->fw_ver) {
1066         case 0:
1067         case 1:
1068                 raw = (const struct wmfw_adsp_alg_data *)*data;
1069                 *data = raw->data;
1070
1071                 blk->id = le32_to_cpu(raw->id);
1072                 blk->name = raw->name;
1073                 blk->name_len = strlen(raw->name);
1074                 blk->ncoeff = le32_to_cpu(raw->ncoeff);
1075                 break;
1076         default:
1077                 blk->id = cs_dsp_coeff_parse_int(sizeof(raw->id), data);
1078                 blk->name_len = cs_dsp_coeff_parse_string(sizeof(u8), data,
1079                                                           &blk->name);
1080                 cs_dsp_coeff_parse_string(sizeof(u16), data, NULL);
1081                 blk->ncoeff = cs_dsp_coeff_parse_int(sizeof(raw->ncoeff), data);
1082                 break;
1083         }
1084
1085         cs_dsp_dbg(dsp, "Algorithm ID: %#x\n", blk->id);
1086         cs_dsp_dbg(dsp, "Algorithm name: %.*s\n", blk->name_len, blk->name);
1087         cs_dsp_dbg(dsp, "# of coefficient descriptors: %#x\n", blk->ncoeff);
1088 }
1089
1090 static inline void cs_dsp_coeff_parse_coeff(struct cs_dsp *dsp, const u8 **data,
1091                                             struct cs_dsp_coeff_parsed_coeff *blk)
1092 {
1093         const struct wmfw_adsp_coeff_data *raw;
1094         const u8 *tmp;
1095         int length;
1096
1097         switch (dsp->fw_ver) {
1098         case 0:
1099         case 1:
1100                 raw = (const struct wmfw_adsp_coeff_data *)*data;
1101                 *data = *data + sizeof(raw->hdr) + le32_to_cpu(raw->hdr.size);
1102
1103                 blk->offset = le16_to_cpu(raw->hdr.offset);
1104                 blk->mem_type = le16_to_cpu(raw->hdr.type);
1105                 blk->name = raw->name;
1106                 blk->name_len = strlen(raw->name);
1107                 blk->ctl_type = le16_to_cpu(raw->ctl_type);
1108                 blk->flags = le16_to_cpu(raw->flags);
1109                 blk->len = le32_to_cpu(raw->len);
1110                 break;
1111         default:
1112                 tmp = *data;
1113                 blk->offset = cs_dsp_coeff_parse_int(sizeof(raw->hdr.offset), &tmp);
1114                 blk->mem_type = cs_dsp_coeff_parse_int(sizeof(raw->hdr.type), &tmp);
1115                 length = cs_dsp_coeff_parse_int(sizeof(raw->hdr.size), &tmp);
1116                 blk->name_len = cs_dsp_coeff_parse_string(sizeof(u8), &tmp,
1117                                                           &blk->name);
1118                 cs_dsp_coeff_parse_string(sizeof(u8), &tmp, NULL);
1119                 cs_dsp_coeff_parse_string(sizeof(u16), &tmp, NULL);
1120                 blk->ctl_type = cs_dsp_coeff_parse_int(sizeof(raw->ctl_type), &tmp);
1121                 blk->flags = cs_dsp_coeff_parse_int(sizeof(raw->flags), &tmp);
1122                 blk->len = cs_dsp_coeff_parse_int(sizeof(raw->len), &tmp);
1123
1124                 *data = *data + sizeof(raw->hdr) + length;
1125                 break;
1126         }
1127
1128         cs_dsp_dbg(dsp, "\tCoefficient type: %#x\n", blk->mem_type);
1129         cs_dsp_dbg(dsp, "\tCoefficient offset: %#x\n", blk->offset);
1130         cs_dsp_dbg(dsp, "\tCoefficient name: %.*s\n", blk->name_len, blk->name);
1131         cs_dsp_dbg(dsp, "\tCoefficient flags: %#x\n", blk->flags);
1132         cs_dsp_dbg(dsp, "\tALSA control type: %#x\n", blk->ctl_type);
1133         cs_dsp_dbg(dsp, "\tALSA control len: %#x\n", blk->len);
1134 }
1135
1136 static int cs_dsp_check_coeff_flags(struct cs_dsp *dsp,
1137                                     const struct cs_dsp_coeff_parsed_coeff *coeff_blk,
1138                                     unsigned int f_required,
1139                                     unsigned int f_illegal)
1140 {
1141         if ((coeff_blk->flags & f_illegal) ||
1142             ((coeff_blk->flags & f_required) != f_required)) {
1143                 cs_dsp_err(dsp, "Illegal flags 0x%x for control type 0x%x\n",
1144                            coeff_blk->flags, coeff_blk->ctl_type);
1145                 return -EINVAL;
1146         }
1147
1148         return 0;
1149 }
1150
1151 static int cs_dsp_parse_coeff(struct cs_dsp *dsp,
1152                               const struct wmfw_region *region)
1153 {
1154         struct cs_dsp_alg_region alg_region = {};
1155         struct cs_dsp_coeff_parsed_alg alg_blk;
1156         struct cs_dsp_coeff_parsed_coeff coeff_blk;
1157         const u8 *data = region->data;
1158         int i, ret;
1159
1160         cs_dsp_coeff_parse_alg(dsp, &data, &alg_blk);
1161         for (i = 0; i < alg_blk.ncoeff; i++) {
1162                 cs_dsp_coeff_parse_coeff(dsp, &data, &coeff_blk);
1163
1164                 switch (coeff_blk.ctl_type) {
1165                 case WMFW_CTL_TYPE_BYTES:
1166                         break;
1167                 case WMFW_CTL_TYPE_ACKED:
1168                         if (coeff_blk.flags & WMFW_CTL_FLAG_SYS)
1169                                 continue;       /* ignore */
1170
1171                         ret = cs_dsp_check_coeff_flags(dsp, &coeff_blk,
1172                                                        WMFW_CTL_FLAG_VOLATILE |
1173                                                        WMFW_CTL_FLAG_WRITEABLE |
1174                                                        WMFW_CTL_FLAG_READABLE,
1175                                                        0);
1176                         if (ret)
1177                                 return -EINVAL;
1178                         break;
1179                 case WMFW_CTL_TYPE_HOSTEVENT:
1180                 case WMFW_CTL_TYPE_FWEVENT:
1181                         ret = cs_dsp_check_coeff_flags(dsp, &coeff_blk,
1182                                                        WMFW_CTL_FLAG_SYS |
1183                                                        WMFW_CTL_FLAG_VOLATILE |
1184                                                        WMFW_CTL_FLAG_WRITEABLE |
1185                                                        WMFW_CTL_FLAG_READABLE,
1186                                                        0);
1187                         if (ret)
1188                                 return -EINVAL;
1189                         break;
1190                 case WMFW_CTL_TYPE_HOST_BUFFER:
1191                         ret = cs_dsp_check_coeff_flags(dsp, &coeff_blk,
1192                                                        WMFW_CTL_FLAG_SYS |
1193                                                        WMFW_CTL_FLAG_VOLATILE |
1194                                                        WMFW_CTL_FLAG_READABLE,
1195                                                        0);
1196                         if (ret)
1197                                 return -EINVAL;
1198                         break;
1199                 default:
1200                         cs_dsp_err(dsp, "Unknown control type: %d\n",
1201                                    coeff_blk.ctl_type);
1202                         return -EINVAL;
1203                 }
1204
1205                 alg_region.type = coeff_blk.mem_type;
1206                 alg_region.alg = alg_blk.id;
1207
1208                 ret = cs_dsp_create_control(dsp, &alg_region,
1209                                             coeff_blk.offset,
1210                                             coeff_blk.len,
1211                                             coeff_blk.name,
1212                                             coeff_blk.name_len,
1213                                             coeff_blk.flags,
1214                                             coeff_blk.ctl_type);
1215                 if (ret < 0)
1216                         cs_dsp_err(dsp, "Failed to create control: %.*s, %d\n",
1217                                    coeff_blk.name_len, coeff_blk.name, ret);
1218         }
1219
1220         return 0;
1221 }
1222
1223 static unsigned int cs_dsp_adsp1_parse_sizes(struct cs_dsp *dsp,
1224                                              const char * const file,
1225                                              unsigned int pos,
1226                                              const struct firmware *firmware)
1227 {
1228         const struct wmfw_adsp1_sizes *adsp1_sizes;
1229
1230         adsp1_sizes = (void *)&firmware->data[pos];
1231
1232         cs_dsp_dbg(dsp, "%s: %d DM, %d PM, %d ZM\n", file,
1233                    le32_to_cpu(adsp1_sizes->dm), le32_to_cpu(adsp1_sizes->pm),
1234                    le32_to_cpu(adsp1_sizes->zm));
1235
1236         return pos + sizeof(*adsp1_sizes);
1237 }
1238
1239 static unsigned int cs_dsp_adsp2_parse_sizes(struct cs_dsp *dsp,
1240                                              const char * const file,
1241                                              unsigned int pos,
1242                                              const struct firmware *firmware)
1243 {
1244         const struct wmfw_adsp2_sizes *adsp2_sizes;
1245
1246         adsp2_sizes = (void *)&firmware->data[pos];
1247
1248         cs_dsp_dbg(dsp, "%s: %d XM, %d YM %d PM, %d ZM\n", file,
1249                    le32_to_cpu(adsp2_sizes->xm), le32_to_cpu(adsp2_sizes->ym),
1250                    le32_to_cpu(adsp2_sizes->pm), le32_to_cpu(adsp2_sizes->zm));
1251
1252         return pos + sizeof(*adsp2_sizes);
1253 }
1254
1255 static bool cs_dsp_validate_version(struct cs_dsp *dsp, unsigned int version)
1256 {
1257         switch (version) {
1258         case 0:
1259                 cs_dsp_warn(dsp, "Deprecated file format %d\n", version);
1260                 return true;
1261         case 1:
1262         case 2:
1263                 return true;
1264         default:
1265                 return false;
1266         }
1267 }
1268
1269 static bool cs_dsp_halo_validate_version(struct cs_dsp *dsp, unsigned int version)
1270 {
1271         switch (version) {
1272         case 3:
1273                 return true;
1274         default:
1275                 return false;
1276         }
1277 }
1278
1279 static int cs_dsp_load(struct cs_dsp *dsp, const struct firmware *firmware,
1280                        const char *file)
1281 {
1282         LIST_HEAD(buf_list);
1283         struct regmap *regmap = dsp->regmap;
1284         unsigned int pos = 0;
1285         const struct wmfw_header *header;
1286         const struct wmfw_adsp1_sizes *adsp1_sizes;
1287         const struct wmfw_footer *footer;
1288         const struct wmfw_region *region;
1289         const struct cs_dsp_region *mem;
1290         const char *region_name;
1291         char *text = NULL;
1292         struct cs_dsp_buf *buf;
1293         unsigned int reg;
1294         int regions = 0;
1295         int ret, offset, type;
1296
1297         ret = -EINVAL;
1298
1299         pos = sizeof(*header) + sizeof(*adsp1_sizes) + sizeof(*footer);
1300         if (pos >= firmware->size) {
1301                 cs_dsp_err(dsp, "%s: file too short, %zu bytes\n",
1302                            file, firmware->size);
1303                 goto out_fw;
1304         }
1305
1306         header = (void *)&firmware->data[0];
1307
1308         if (memcmp(&header->magic[0], "WMFW", 4) != 0) {
1309                 cs_dsp_err(dsp, "%s: invalid magic\n", file);
1310                 goto out_fw;
1311         }
1312
1313         if (!dsp->ops->validate_version(dsp, header->ver)) {
1314                 cs_dsp_err(dsp, "%s: unknown file format %d\n",
1315                            file, header->ver);
1316                 goto out_fw;
1317         }
1318
1319         cs_dsp_info(dsp, "Firmware version: %d\n", header->ver);
1320         dsp->fw_ver = header->ver;
1321
1322         if (header->core != dsp->type) {
1323                 cs_dsp_err(dsp, "%s: invalid core %d != %d\n",
1324                            file, header->core, dsp->type);
1325                 goto out_fw;
1326         }
1327
1328         pos = sizeof(*header);
1329         pos = dsp->ops->parse_sizes(dsp, file, pos, firmware);
1330
1331         footer = (void *)&firmware->data[pos];
1332         pos += sizeof(*footer);
1333
1334         if (le32_to_cpu(header->len) != pos) {
1335                 cs_dsp_err(dsp, "%s: unexpected header length %d\n",
1336                            file, le32_to_cpu(header->len));
1337                 goto out_fw;
1338         }
1339
1340         cs_dsp_dbg(dsp, "%s: timestamp %llu\n", file,
1341                    le64_to_cpu(footer->timestamp));
1342
1343         while (pos < firmware->size &&
1344                sizeof(*region) < firmware->size - pos) {
1345                 region = (void *)&(firmware->data[pos]);
1346                 region_name = "Unknown";
1347                 reg = 0;
1348                 text = NULL;
1349                 offset = le32_to_cpu(region->offset) & 0xffffff;
1350                 type = be32_to_cpu(region->type) & 0xff;
1351
1352                 switch (type) {
1353                 case WMFW_NAME_TEXT:
1354                         region_name = "Firmware name";
1355                         text = kzalloc(le32_to_cpu(region->len) + 1,
1356                                        GFP_KERNEL);
1357                         break;
1358                 case WMFW_ALGORITHM_DATA:
1359                         region_name = "Algorithm";
1360                         ret = cs_dsp_parse_coeff(dsp, region);
1361                         if (ret != 0)
1362                                 goto out_fw;
1363                         break;
1364                 case WMFW_INFO_TEXT:
1365                         region_name = "Information";
1366                         text = kzalloc(le32_to_cpu(region->len) + 1,
1367                                        GFP_KERNEL);
1368                         break;
1369                 case WMFW_ABSOLUTE:
1370                         region_name = "Absolute";
1371                         reg = offset;
1372                         break;
1373                 case WMFW_ADSP1_PM:
1374                 case WMFW_ADSP1_DM:
1375                 case WMFW_ADSP2_XM:
1376                 case WMFW_ADSP2_YM:
1377                 case WMFW_ADSP1_ZM:
1378                 case WMFW_HALO_PM_PACKED:
1379                 case WMFW_HALO_XM_PACKED:
1380                 case WMFW_HALO_YM_PACKED:
1381                         mem = cs_dsp_find_region(dsp, type);
1382                         if (!mem) {
1383                                 cs_dsp_err(dsp, "No region of type: %x\n", type);
1384                                 ret = -EINVAL;
1385                                 goto out_fw;
1386                         }
1387
1388                         region_name = cs_dsp_mem_region_name(type);
1389                         reg = dsp->ops->region_to_reg(mem, offset);
1390                         break;
1391                 default:
1392                         cs_dsp_warn(dsp,
1393                                     "%s.%d: Unknown region type %x at %d(%x)\n",
1394                                     file, regions, type, pos, pos);
1395                         break;
1396                 }
1397
1398                 cs_dsp_dbg(dsp, "%s.%d: %d bytes at %d in %s\n", file,
1399                            regions, le32_to_cpu(region->len), offset,
1400                            region_name);
1401
1402                 if (le32_to_cpu(region->len) >
1403                     firmware->size - pos - sizeof(*region)) {
1404                         cs_dsp_err(dsp,
1405                                    "%s.%d: %s region len %d bytes exceeds file length %zu\n",
1406                                    file, regions, region_name,
1407                                    le32_to_cpu(region->len), firmware->size);
1408                         ret = -EINVAL;
1409                         goto out_fw;
1410                 }
1411
1412                 if (text) {
1413                         memcpy(text, region->data, le32_to_cpu(region->len));
1414                         cs_dsp_info(dsp, "%s: %s\n", file, text);
1415                         kfree(text);
1416                         text = NULL;
1417                 }
1418
1419                 if (reg) {
1420                         buf = cs_dsp_buf_alloc(region->data,
1421                                                le32_to_cpu(region->len),
1422                                                &buf_list);
1423                         if (!buf) {
1424                                 cs_dsp_err(dsp, "Out of memory\n");
1425                                 ret = -ENOMEM;
1426                                 goto out_fw;
1427                         }
1428
1429                         ret = regmap_raw_write_async(regmap, reg, buf->buf,
1430                                                      le32_to_cpu(region->len));
1431                         if (ret != 0) {
1432                                 cs_dsp_err(dsp,
1433                                            "%s.%d: Failed to write %d bytes at %d in %s: %d\n",
1434                                            file, regions,
1435                                            le32_to_cpu(region->len), offset,
1436                                            region_name, ret);
1437                                 goto out_fw;
1438                         }
1439                 }
1440
1441                 pos += le32_to_cpu(region->len) + sizeof(*region);
1442                 regions++;
1443         }
1444
1445         ret = regmap_async_complete(regmap);
1446         if (ret != 0) {
1447                 cs_dsp_err(dsp, "Failed to complete async write: %d\n", ret);
1448                 goto out_fw;
1449         }
1450
1451         if (pos > firmware->size)
1452                 cs_dsp_warn(dsp, "%s.%d: %zu bytes at end of file\n",
1453                             file, regions, pos - firmware->size);
1454
1455         cs_dsp_debugfs_save_wmfwname(dsp, file);
1456
1457 out_fw:
1458         regmap_async_complete(regmap);
1459         cs_dsp_buf_free(&buf_list);
1460         kfree(text);
1461
1462         return ret;
1463 }
1464
1465 /**
1466  * cs_dsp_get_ctl() - Finds a matching coefficient control
1467  * @dsp: pointer to DSP structure
1468  * @name: pointer to string to match with a control's subname
1469  * @type: the algorithm type to match
1470  * @alg: the algorithm id to match
1471  *
1472  * Find cs_dsp_coeff_ctl with input name as its subname
1473  *
1474  * Return: pointer to the control on success, NULL if not found
1475  */
1476 struct cs_dsp_coeff_ctl *cs_dsp_get_ctl(struct cs_dsp *dsp, const char *name, int type,
1477                                         unsigned int alg)
1478 {
1479         struct cs_dsp_coeff_ctl *pos, *rslt = NULL;
1480
1481         lockdep_assert_held(&dsp->pwr_lock);
1482
1483         list_for_each_entry(pos, &dsp->ctl_list, list) {
1484                 if (!pos->subname)
1485                         continue;
1486                 if (strncmp(pos->subname, name, pos->subname_len) == 0 &&
1487                     pos->fw_name == dsp->fw_name &&
1488                     pos->alg_region.alg == alg &&
1489                     pos->alg_region.type == type) {
1490                         rslt = pos;
1491                         break;
1492                 }
1493         }
1494
1495         return rslt;
1496 }
1497 EXPORT_SYMBOL_GPL(cs_dsp_get_ctl);
1498
1499 static void cs_dsp_ctl_fixup_base(struct cs_dsp *dsp,
1500                                   const struct cs_dsp_alg_region *alg_region)
1501 {
1502         struct cs_dsp_coeff_ctl *ctl;
1503
1504         list_for_each_entry(ctl, &dsp->ctl_list, list) {
1505                 if (ctl->fw_name == dsp->fw_name &&
1506                     alg_region->alg == ctl->alg_region.alg &&
1507                     alg_region->type == ctl->alg_region.type) {
1508                         ctl->alg_region.base = alg_region->base;
1509                 }
1510         }
1511 }
1512
1513 static void *cs_dsp_read_algs(struct cs_dsp *dsp, size_t n_algs,
1514                               const struct cs_dsp_region *mem,
1515                               unsigned int pos, unsigned int len)
1516 {
1517         void *alg;
1518         unsigned int reg;
1519         int ret;
1520         __be32 val;
1521
1522         if (n_algs == 0) {
1523                 cs_dsp_err(dsp, "No algorithms\n");
1524                 return ERR_PTR(-EINVAL);
1525         }
1526
1527         if (n_algs > 1024) {
1528                 cs_dsp_err(dsp, "Algorithm count %zx excessive\n", n_algs);
1529                 return ERR_PTR(-EINVAL);
1530         }
1531
1532         /* Read the terminator first to validate the length */
1533         reg = dsp->ops->region_to_reg(mem, pos + len);
1534
1535         ret = regmap_raw_read(dsp->regmap, reg, &val, sizeof(val));
1536         if (ret != 0) {
1537                 cs_dsp_err(dsp, "Failed to read algorithm list end: %d\n",
1538                            ret);
1539                 return ERR_PTR(ret);
1540         }
1541
1542         if (be32_to_cpu(val) != 0xbedead)
1543                 cs_dsp_warn(dsp, "Algorithm list end %x 0x%x != 0xbedead\n",
1544                             reg, be32_to_cpu(val));
1545
1546         /* Convert length from DSP words to bytes */
1547         len *= sizeof(u32);
1548
1549         alg = kzalloc(len, GFP_KERNEL | GFP_DMA);
1550         if (!alg)
1551                 return ERR_PTR(-ENOMEM);
1552
1553         reg = dsp->ops->region_to_reg(mem, pos);
1554
1555         ret = regmap_raw_read(dsp->regmap, reg, alg, len);
1556         if (ret != 0) {
1557                 cs_dsp_err(dsp, "Failed to read algorithm list: %d\n", ret);
1558                 kfree(alg);
1559                 return ERR_PTR(ret);
1560         }
1561
1562         return alg;
1563 }
1564
1565 /**
1566  * cs_dsp_find_alg_region() - Finds a matching algorithm region
1567  * @dsp: pointer to DSP structure
1568  * @type: the algorithm type to match
1569  * @id: the algorithm id to match
1570  *
1571  * Return: Pointer to matching algorithm region, or NULL if not found.
1572  */
1573 struct cs_dsp_alg_region *cs_dsp_find_alg_region(struct cs_dsp *dsp,
1574                                                  int type, unsigned int id)
1575 {
1576         struct cs_dsp_alg_region *alg_region;
1577
1578         lockdep_assert_held(&dsp->pwr_lock);
1579
1580         list_for_each_entry(alg_region, &dsp->alg_regions, list) {
1581                 if (id == alg_region->alg && type == alg_region->type)
1582                         return alg_region;
1583         }
1584
1585         return NULL;
1586 }
1587 EXPORT_SYMBOL_GPL(cs_dsp_find_alg_region);
1588
1589 static struct cs_dsp_alg_region *cs_dsp_create_region(struct cs_dsp *dsp,
1590                                                       int type, __be32 id,
1591                                                       __be32 ver, __be32 base)
1592 {
1593         struct cs_dsp_alg_region *alg_region;
1594
1595         alg_region = kzalloc(sizeof(*alg_region), GFP_KERNEL);
1596         if (!alg_region)
1597                 return ERR_PTR(-ENOMEM);
1598
1599         alg_region->type = type;
1600         alg_region->alg = be32_to_cpu(id);
1601         alg_region->ver = be32_to_cpu(ver);
1602         alg_region->base = be32_to_cpu(base);
1603
1604         list_add_tail(&alg_region->list, &dsp->alg_regions);
1605
1606         if (dsp->fw_ver > 0)
1607                 cs_dsp_ctl_fixup_base(dsp, alg_region);
1608
1609         return alg_region;
1610 }
1611
1612 static void cs_dsp_free_alg_regions(struct cs_dsp *dsp)
1613 {
1614         struct cs_dsp_alg_region *alg_region;
1615
1616         while (!list_empty(&dsp->alg_regions)) {
1617                 alg_region = list_first_entry(&dsp->alg_regions,
1618                                               struct cs_dsp_alg_region,
1619                                               list);
1620                 list_del(&alg_region->list);
1621                 kfree(alg_region);
1622         }
1623 }
1624
1625 static void cs_dsp_parse_wmfw_id_header(struct cs_dsp *dsp,
1626                                         struct wmfw_id_hdr *fw, int nalgs)
1627 {
1628         dsp->fw_id = be32_to_cpu(fw->id);
1629         dsp->fw_id_version = be32_to_cpu(fw->ver);
1630
1631         cs_dsp_info(dsp, "Firmware: %x v%d.%d.%d, %d algorithms\n",
1632                     dsp->fw_id, (dsp->fw_id_version & 0xff0000) >> 16,
1633                     (dsp->fw_id_version & 0xff00) >> 8, dsp->fw_id_version & 0xff,
1634                     nalgs);
1635 }
1636
1637 static void cs_dsp_parse_wmfw_v3_id_header(struct cs_dsp *dsp,
1638                                            struct wmfw_v3_id_hdr *fw, int nalgs)
1639 {
1640         dsp->fw_id = be32_to_cpu(fw->id);
1641         dsp->fw_id_version = be32_to_cpu(fw->ver);
1642         dsp->fw_vendor_id = be32_to_cpu(fw->vendor_id);
1643
1644         cs_dsp_info(dsp, "Firmware: %x vendor: 0x%x v%d.%d.%d, %d algorithms\n",
1645                     dsp->fw_id, dsp->fw_vendor_id,
1646                     (dsp->fw_id_version & 0xff0000) >> 16,
1647                     (dsp->fw_id_version & 0xff00) >> 8, dsp->fw_id_version & 0xff,
1648                     nalgs);
1649 }
1650
1651 static int cs_dsp_create_regions(struct cs_dsp *dsp, __be32 id, __be32 ver,
1652                                  int nregions, const int *type, __be32 *base)
1653 {
1654         struct cs_dsp_alg_region *alg_region;
1655         int i;
1656
1657         for (i = 0; i < nregions; i++) {
1658                 alg_region = cs_dsp_create_region(dsp, type[i], id, ver, base[i]);
1659                 if (IS_ERR(alg_region))
1660                         return PTR_ERR(alg_region);
1661         }
1662
1663         return 0;
1664 }
1665
1666 static int cs_dsp_adsp1_setup_algs(struct cs_dsp *dsp)
1667 {
1668         struct wmfw_adsp1_id_hdr adsp1_id;
1669         struct wmfw_adsp1_alg_hdr *adsp1_alg;
1670         struct cs_dsp_alg_region *alg_region;
1671         const struct cs_dsp_region *mem;
1672         unsigned int pos, len;
1673         size_t n_algs;
1674         int i, ret;
1675
1676         mem = cs_dsp_find_region(dsp, WMFW_ADSP1_DM);
1677         if (WARN_ON(!mem))
1678                 return -EINVAL;
1679
1680         ret = regmap_raw_read(dsp->regmap, mem->base, &adsp1_id,
1681                               sizeof(adsp1_id));
1682         if (ret != 0) {
1683                 cs_dsp_err(dsp, "Failed to read algorithm info: %d\n",
1684                            ret);
1685                 return ret;
1686         }
1687
1688         n_algs = be32_to_cpu(adsp1_id.n_algs);
1689
1690         cs_dsp_parse_wmfw_id_header(dsp, &adsp1_id.fw, n_algs);
1691
1692         alg_region = cs_dsp_create_region(dsp, WMFW_ADSP1_ZM,
1693                                           adsp1_id.fw.id, adsp1_id.fw.ver,
1694                                           adsp1_id.zm);
1695         if (IS_ERR(alg_region))
1696                 return PTR_ERR(alg_region);
1697
1698         alg_region = cs_dsp_create_region(dsp, WMFW_ADSP1_DM,
1699                                           adsp1_id.fw.id, adsp1_id.fw.ver,
1700                                           adsp1_id.dm);
1701         if (IS_ERR(alg_region))
1702                 return PTR_ERR(alg_region);
1703
1704         /* Calculate offset and length in DSP words */
1705         pos = sizeof(adsp1_id) / sizeof(u32);
1706         len = (sizeof(*adsp1_alg) * n_algs) / sizeof(u32);
1707
1708         adsp1_alg = cs_dsp_read_algs(dsp, n_algs, mem, pos, len);
1709         if (IS_ERR(adsp1_alg))
1710                 return PTR_ERR(adsp1_alg);
1711
1712         for (i = 0; i < n_algs; i++) {
1713                 cs_dsp_info(dsp, "%d: ID %x v%d.%d.%d DM@%x ZM@%x\n",
1714                             i, be32_to_cpu(adsp1_alg[i].alg.id),
1715                             (be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff0000) >> 16,
1716                             (be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff00) >> 8,
1717                             be32_to_cpu(adsp1_alg[i].alg.ver) & 0xff,
1718                             be32_to_cpu(adsp1_alg[i].dm),
1719                             be32_to_cpu(adsp1_alg[i].zm));
1720
1721                 alg_region = cs_dsp_create_region(dsp, WMFW_ADSP1_DM,
1722                                                   adsp1_alg[i].alg.id,
1723                                                   adsp1_alg[i].alg.ver,
1724                                                   adsp1_alg[i].dm);
1725                 if (IS_ERR(alg_region)) {
1726                         ret = PTR_ERR(alg_region);
1727                         goto out;
1728                 }
1729                 if (dsp->fw_ver == 0) {
1730                         if (i + 1 < n_algs) {
1731                                 len = be32_to_cpu(adsp1_alg[i + 1].dm);
1732                                 len -= be32_to_cpu(adsp1_alg[i].dm);
1733                                 len *= 4;
1734                                 cs_dsp_create_control(dsp, alg_region, 0,
1735                                                       len, NULL, 0, 0,
1736                                                       WMFW_CTL_TYPE_BYTES);
1737                         } else {
1738                                 cs_dsp_warn(dsp, "Missing length info for region DM with ID %x\n",
1739                                             be32_to_cpu(adsp1_alg[i].alg.id));
1740                         }
1741                 }
1742
1743                 alg_region = cs_dsp_create_region(dsp, WMFW_ADSP1_ZM,
1744                                                   adsp1_alg[i].alg.id,
1745                                                   adsp1_alg[i].alg.ver,
1746                                                   adsp1_alg[i].zm);
1747                 if (IS_ERR(alg_region)) {
1748                         ret = PTR_ERR(alg_region);
1749                         goto out;
1750                 }
1751                 if (dsp->fw_ver == 0) {
1752                         if (i + 1 < n_algs) {
1753                                 len = be32_to_cpu(adsp1_alg[i + 1].zm);
1754                                 len -= be32_to_cpu(adsp1_alg[i].zm);
1755                                 len *= 4;
1756                                 cs_dsp_create_control(dsp, alg_region, 0,
1757                                                       len, NULL, 0, 0,
1758                                                       WMFW_CTL_TYPE_BYTES);
1759                         } else {
1760                                 cs_dsp_warn(dsp, "Missing length info for region ZM with ID %x\n",
1761                                             be32_to_cpu(adsp1_alg[i].alg.id));
1762                         }
1763                 }
1764         }
1765
1766 out:
1767         kfree(adsp1_alg);
1768         return ret;
1769 }
1770
1771 static int cs_dsp_adsp2_setup_algs(struct cs_dsp *dsp)
1772 {
1773         struct wmfw_adsp2_id_hdr adsp2_id;
1774         struct wmfw_adsp2_alg_hdr *adsp2_alg;
1775         struct cs_dsp_alg_region *alg_region;
1776         const struct cs_dsp_region *mem;
1777         unsigned int pos, len;
1778         size_t n_algs;
1779         int i, ret;
1780
1781         mem = cs_dsp_find_region(dsp, WMFW_ADSP2_XM);
1782         if (WARN_ON(!mem))
1783                 return -EINVAL;
1784
1785         ret = regmap_raw_read(dsp->regmap, mem->base, &adsp2_id,
1786                               sizeof(adsp2_id));
1787         if (ret != 0) {
1788                 cs_dsp_err(dsp, "Failed to read algorithm info: %d\n",
1789                            ret);
1790                 return ret;
1791         }
1792
1793         n_algs = be32_to_cpu(adsp2_id.n_algs);
1794
1795         cs_dsp_parse_wmfw_id_header(dsp, &adsp2_id.fw, n_algs);
1796
1797         alg_region = cs_dsp_create_region(dsp, WMFW_ADSP2_XM,
1798                                           adsp2_id.fw.id, adsp2_id.fw.ver,
1799                                           adsp2_id.xm);
1800         if (IS_ERR(alg_region))
1801                 return PTR_ERR(alg_region);
1802
1803         alg_region = cs_dsp_create_region(dsp, WMFW_ADSP2_YM,
1804                                           adsp2_id.fw.id, adsp2_id.fw.ver,
1805                                           adsp2_id.ym);
1806         if (IS_ERR(alg_region))
1807                 return PTR_ERR(alg_region);
1808
1809         alg_region = cs_dsp_create_region(dsp, WMFW_ADSP2_ZM,
1810                                           adsp2_id.fw.id, adsp2_id.fw.ver,
1811                                           adsp2_id.zm);
1812         if (IS_ERR(alg_region))
1813                 return PTR_ERR(alg_region);
1814
1815         /* Calculate offset and length in DSP words */
1816         pos = sizeof(adsp2_id) / sizeof(u32);
1817         len = (sizeof(*adsp2_alg) * n_algs) / sizeof(u32);
1818
1819         adsp2_alg = cs_dsp_read_algs(dsp, n_algs, mem, pos, len);
1820         if (IS_ERR(adsp2_alg))
1821                 return PTR_ERR(adsp2_alg);
1822
1823         for (i = 0; i < n_algs; i++) {
1824                 cs_dsp_info(dsp,
1825                             "%d: ID %x v%d.%d.%d XM@%x YM@%x ZM@%x\n",
1826                             i, be32_to_cpu(adsp2_alg[i].alg.id),
1827                             (be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff0000) >> 16,
1828                             (be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff00) >> 8,
1829                             be32_to_cpu(adsp2_alg[i].alg.ver) & 0xff,
1830                             be32_to_cpu(adsp2_alg[i].xm),
1831                             be32_to_cpu(adsp2_alg[i].ym),
1832                             be32_to_cpu(adsp2_alg[i].zm));
1833
1834                 alg_region = cs_dsp_create_region(dsp, WMFW_ADSP2_XM,
1835                                                   adsp2_alg[i].alg.id,
1836                                                   adsp2_alg[i].alg.ver,
1837                                                   adsp2_alg[i].xm);
1838                 if (IS_ERR(alg_region)) {
1839                         ret = PTR_ERR(alg_region);
1840                         goto out;
1841                 }
1842                 if (dsp->fw_ver == 0) {
1843                         if (i + 1 < n_algs) {
1844                                 len = be32_to_cpu(adsp2_alg[i + 1].xm);
1845                                 len -= be32_to_cpu(adsp2_alg[i].xm);
1846                                 len *= 4;
1847                                 cs_dsp_create_control(dsp, alg_region, 0,
1848                                                       len, NULL, 0, 0,
1849                                                       WMFW_CTL_TYPE_BYTES);
1850                         } else {
1851                                 cs_dsp_warn(dsp, "Missing length info for region XM with ID %x\n",
1852                                             be32_to_cpu(adsp2_alg[i].alg.id));
1853                         }
1854                 }
1855
1856                 alg_region = cs_dsp_create_region(dsp, WMFW_ADSP2_YM,
1857                                                   adsp2_alg[i].alg.id,
1858                                                   adsp2_alg[i].alg.ver,
1859                                                   adsp2_alg[i].ym);
1860                 if (IS_ERR(alg_region)) {
1861                         ret = PTR_ERR(alg_region);
1862                         goto out;
1863                 }
1864                 if (dsp->fw_ver == 0) {
1865                         if (i + 1 < n_algs) {
1866                                 len = be32_to_cpu(adsp2_alg[i + 1].ym);
1867                                 len -= be32_to_cpu(adsp2_alg[i].ym);
1868                                 len *= 4;
1869                                 cs_dsp_create_control(dsp, alg_region, 0,
1870                                                       len, NULL, 0, 0,
1871                                                       WMFW_CTL_TYPE_BYTES);
1872                         } else {
1873                                 cs_dsp_warn(dsp, "Missing length info for region YM with ID %x\n",
1874                                             be32_to_cpu(adsp2_alg[i].alg.id));
1875                         }
1876                 }
1877
1878                 alg_region = cs_dsp_create_region(dsp, WMFW_ADSP2_ZM,
1879                                                   adsp2_alg[i].alg.id,
1880                                                   adsp2_alg[i].alg.ver,
1881                                                   adsp2_alg[i].zm);
1882                 if (IS_ERR(alg_region)) {
1883                         ret = PTR_ERR(alg_region);
1884                         goto out;
1885                 }
1886                 if (dsp->fw_ver == 0) {
1887                         if (i + 1 < n_algs) {
1888                                 len = be32_to_cpu(adsp2_alg[i + 1].zm);
1889                                 len -= be32_to_cpu(adsp2_alg[i].zm);
1890                                 len *= 4;
1891                                 cs_dsp_create_control(dsp, alg_region, 0,
1892                                                       len, NULL, 0, 0,
1893                                                       WMFW_CTL_TYPE_BYTES);
1894                         } else {
1895                                 cs_dsp_warn(dsp, "Missing length info for region ZM with ID %x\n",
1896                                             be32_to_cpu(adsp2_alg[i].alg.id));
1897                         }
1898                 }
1899         }
1900
1901 out:
1902         kfree(adsp2_alg);
1903         return ret;
1904 }
1905
1906 static int cs_dsp_halo_create_regions(struct cs_dsp *dsp, __be32 id, __be32 ver,
1907                                       __be32 xm_base, __be32 ym_base)
1908 {
1909         static const int types[] = {
1910                 WMFW_ADSP2_XM, WMFW_HALO_XM_PACKED,
1911                 WMFW_ADSP2_YM, WMFW_HALO_YM_PACKED
1912         };
1913         __be32 bases[] = { xm_base, xm_base, ym_base, ym_base };
1914
1915         return cs_dsp_create_regions(dsp, id, ver, ARRAY_SIZE(types), types, bases);
1916 }
1917
1918 static int cs_dsp_halo_setup_algs(struct cs_dsp *dsp)
1919 {
1920         struct wmfw_halo_id_hdr halo_id;
1921         struct wmfw_halo_alg_hdr *halo_alg;
1922         const struct cs_dsp_region *mem;
1923         unsigned int pos, len;
1924         size_t n_algs;
1925         int i, ret;
1926
1927         mem = cs_dsp_find_region(dsp, WMFW_ADSP2_XM);
1928         if (WARN_ON(!mem))
1929                 return -EINVAL;
1930
1931         ret = regmap_raw_read(dsp->regmap, mem->base, &halo_id,
1932                               sizeof(halo_id));
1933         if (ret != 0) {
1934                 cs_dsp_err(dsp, "Failed to read algorithm info: %d\n",
1935                            ret);
1936                 return ret;
1937         }
1938
1939         n_algs = be32_to_cpu(halo_id.n_algs);
1940
1941         cs_dsp_parse_wmfw_v3_id_header(dsp, &halo_id.fw, n_algs);
1942
1943         ret = cs_dsp_halo_create_regions(dsp, halo_id.fw.id, halo_id.fw.ver,
1944                                          halo_id.xm_base, halo_id.ym_base);
1945         if (ret)
1946                 return ret;
1947
1948         /* Calculate offset and length in DSP words */
1949         pos = sizeof(halo_id) / sizeof(u32);
1950         len = (sizeof(*halo_alg) * n_algs) / sizeof(u32);
1951
1952         halo_alg = cs_dsp_read_algs(dsp, n_algs, mem, pos, len);
1953         if (IS_ERR(halo_alg))
1954                 return PTR_ERR(halo_alg);
1955
1956         for (i = 0; i < n_algs; i++) {
1957                 cs_dsp_info(dsp,
1958                             "%d: ID %x v%d.%d.%d XM@%x YM@%x\n",
1959                             i, be32_to_cpu(halo_alg[i].alg.id),
1960                             (be32_to_cpu(halo_alg[i].alg.ver) & 0xff0000) >> 16,
1961                             (be32_to_cpu(halo_alg[i].alg.ver) & 0xff00) >> 8,
1962                             be32_to_cpu(halo_alg[i].alg.ver) & 0xff,
1963                             be32_to_cpu(halo_alg[i].xm_base),
1964                             be32_to_cpu(halo_alg[i].ym_base));
1965
1966                 ret = cs_dsp_halo_create_regions(dsp, halo_alg[i].alg.id,
1967                                                  halo_alg[i].alg.ver,
1968                                                  halo_alg[i].xm_base,
1969                                                  halo_alg[i].ym_base);
1970                 if (ret)
1971                         goto out;
1972         }
1973
1974 out:
1975         kfree(halo_alg);
1976         return ret;
1977 }
1978
1979 static int cs_dsp_load_coeff(struct cs_dsp *dsp, const struct firmware *firmware,
1980                              const char *file)
1981 {
1982         LIST_HEAD(buf_list);
1983         struct regmap *regmap = dsp->regmap;
1984         struct wmfw_coeff_hdr *hdr;
1985         struct wmfw_coeff_item *blk;
1986         const struct cs_dsp_region *mem;
1987         struct cs_dsp_alg_region *alg_region;
1988         const char *region_name;
1989         int ret, pos, blocks, type, offset, reg, version;
1990         char *text = NULL;
1991         struct cs_dsp_buf *buf;
1992
1993         if (!firmware)
1994                 return 0;
1995
1996         ret = -EINVAL;
1997
1998         if (sizeof(*hdr) >= firmware->size) {
1999                 cs_dsp_err(dsp, "%s: coefficient file too short, %zu bytes\n",
2000                            file, firmware->size);
2001                 goto out_fw;
2002         }
2003
2004         hdr = (void *)&firmware->data[0];
2005         if (memcmp(hdr->magic, "WMDR", 4) != 0) {
2006                 cs_dsp_err(dsp, "%s: invalid coefficient magic\n", file);
2007                 goto out_fw;
2008         }
2009
2010         switch (be32_to_cpu(hdr->rev) & 0xff) {
2011         case 1:
2012         case 2:
2013                 break;
2014         default:
2015                 cs_dsp_err(dsp, "%s: Unsupported coefficient file format %d\n",
2016                            file, be32_to_cpu(hdr->rev) & 0xff);
2017                 ret = -EINVAL;
2018                 goto out_fw;
2019         }
2020
2021         cs_dsp_dbg(dsp, "%s: v%d.%d.%d\n", file,
2022                    (le32_to_cpu(hdr->ver) >> 16) & 0xff,
2023                    (le32_to_cpu(hdr->ver) >>  8) & 0xff,
2024                    le32_to_cpu(hdr->ver) & 0xff);
2025
2026         pos = le32_to_cpu(hdr->len);
2027
2028         blocks = 0;
2029         while (pos < firmware->size &&
2030                sizeof(*blk) < firmware->size - pos) {
2031                 blk = (void *)(&firmware->data[pos]);
2032
2033                 type = le16_to_cpu(blk->type);
2034                 offset = le16_to_cpu(blk->offset);
2035                 version = le32_to_cpu(blk->ver) >> 8;
2036
2037                 cs_dsp_dbg(dsp, "%s.%d: %x v%d.%d.%d\n",
2038                            file, blocks, le32_to_cpu(blk->id),
2039                            (le32_to_cpu(blk->ver) >> 16) & 0xff,
2040                            (le32_to_cpu(blk->ver) >>  8) & 0xff,
2041                            le32_to_cpu(blk->ver) & 0xff);
2042                 cs_dsp_dbg(dsp, "%s.%d: %d bytes at 0x%x in %x\n",
2043                            file, blocks, le32_to_cpu(blk->len), offset, type);
2044
2045                 reg = 0;
2046                 region_name = "Unknown";
2047                 switch (type) {
2048                 case (WMFW_NAME_TEXT << 8):
2049                         text = kzalloc(le32_to_cpu(blk->len) + 1, GFP_KERNEL);
2050                         break;
2051                 case (WMFW_INFO_TEXT << 8):
2052                 case (WMFW_METADATA << 8):
2053                         break;
2054                 case (WMFW_ABSOLUTE << 8):
2055                         /*
2056                          * Old files may use this for global
2057                          * coefficients.
2058                          */
2059                         if (le32_to_cpu(blk->id) == dsp->fw_id &&
2060                             offset == 0) {
2061                                 region_name = "global coefficients";
2062                                 mem = cs_dsp_find_region(dsp, type);
2063                                 if (!mem) {
2064                                         cs_dsp_err(dsp, "No ZM\n");
2065                                         break;
2066                                 }
2067                                 reg = dsp->ops->region_to_reg(mem, 0);
2068
2069                         } else {
2070                                 region_name = "register";
2071                                 reg = offset;
2072                         }
2073                         break;
2074
2075                 case WMFW_ADSP1_DM:
2076                 case WMFW_ADSP1_ZM:
2077                 case WMFW_ADSP2_XM:
2078                 case WMFW_ADSP2_YM:
2079                 case WMFW_HALO_XM_PACKED:
2080                 case WMFW_HALO_YM_PACKED:
2081                 case WMFW_HALO_PM_PACKED:
2082                         cs_dsp_dbg(dsp, "%s.%d: %d bytes in %x for %x\n",
2083                                    file, blocks, le32_to_cpu(blk->len),
2084                                    type, le32_to_cpu(blk->id));
2085
2086                         mem = cs_dsp_find_region(dsp, type);
2087                         if (!mem) {
2088                                 cs_dsp_err(dsp, "No base for region %x\n", type);
2089                                 break;
2090                         }
2091
2092                         alg_region = cs_dsp_find_alg_region(dsp, type,
2093                                                             le32_to_cpu(blk->id));
2094                         if (alg_region) {
2095                                 if (version != alg_region->ver)
2096                                         cs_dsp_warn(dsp,
2097                                                     "Algorithm coefficient version %d.%d.%d but expected %d.%d.%d\n",
2098                                                    (version >> 16) & 0xFF,
2099                                                    (version >> 8) & 0xFF,
2100                                                    version & 0xFF,
2101                                                    (alg_region->ver >> 16) & 0xFF,
2102                                                    (alg_region->ver >> 8) & 0xFF,
2103                                                    alg_region->ver & 0xFF);
2104
2105                                 reg = alg_region->base;
2106                                 reg = dsp->ops->region_to_reg(mem, reg);
2107                                 reg += offset;
2108                         } else {
2109                                 cs_dsp_err(dsp, "No %x for algorithm %x\n",
2110                                            type, le32_to_cpu(blk->id));
2111                         }
2112                         break;
2113
2114                 default:
2115                         cs_dsp_err(dsp, "%s.%d: Unknown region type %x at %d\n",
2116                                    file, blocks, type, pos);
2117                         break;
2118                 }
2119
2120                 if (text) {
2121                         memcpy(text, blk->data, le32_to_cpu(blk->len));
2122                         cs_dsp_info(dsp, "%s: %s\n", dsp->fw_name, text);
2123                         kfree(text);
2124                         text = NULL;
2125                 }
2126
2127                 if (reg) {
2128                         if (le32_to_cpu(blk->len) >
2129                             firmware->size - pos - sizeof(*blk)) {
2130                                 cs_dsp_err(dsp,
2131                                            "%s.%d: %s region len %d bytes exceeds file length %zu\n",
2132                                            file, blocks, region_name,
2133                                            le32_to_cpu(blk->len),
2134                                            firmware->size);
2135                                 ret = -EINVAL;
2136                                 goto out_fw;
2137                         }
2138
2139                         buf = cs_dsp_buf_alloc(blk->data,
2140                                                le32_to_cpu(blk->len),
2141                                                &buf_list);
2142                         if (!buf) {
2143                                 cs_dsp_err(dsp, "Out of memory\n");
2144                                 ret = -ENOMEM;
2145                                 goto out_fw;
2146                         }
2147
2148                         cs_dsp_dbg(dsp, "%s.%d: Writing %d bytes at %x\n",
2149                                    file, blocks, le32_to_cpu(blk->len),
2150                                    reg);
2151                         ret = regmap_raw_write_async(regmap, reg, buf->buf,
2152                                                      le32_to_cpu(blk->len));
2153                         if (ret != 0) {
2154                                 cs_dsp_err(dsp,
2155                                            "%s.%d: Failed to write to %x in %s: %d\n",
2156                                            file, blocks, reg, region_name, ret);
2157                         }
2158                 }
2159
2160                 pos += (le32_to_cpu(blk->len) + sizeof(*blk) + 3) & ~0x03;
2161                 blocks++;
2162         }
2163
2164         ret = regmap_async_complete(regmap);
2165         if (ret != 0)
2166                 cs_dsp_err(dsp, "Failed to complete async write: %d\n", ret);
2167
2168         if (pos > firmware->size)
2169                 cs_dsp_warn(dsp, "%s.%d: %zu bytes at end of file\n",
2170                             file, blocks, pos - firmware->size);
2171
2172         cs_dsp_debugfs_save_binname(dsp, file);
2173
2174 out_fw:
2175         regmap_async_complete(regmap);
2176         cs_dsp_buf_free(&buf_list);
2177         kfree(text);
2178         return ret;
2179 }
2180
2181 static int cs_dsp_create_name(struct cs_dsp *dsp)
2182 {
2183         if (!dsp->name) {
2184                 dsp->name = devm_kasprintf(dsp->dev, GFP_KERNEL, "DSP%d",
2185                                            dsp->num);
2186                 if (!dsp->name)
2187                         return -ENOMEM;
2188         }
2189
2190         return 0;
2191 }
2192
2193 static int cs_dsp_common_init(struct cs_dsp *dsp)
2194 {
2195         int ret;
2196
2197         ret = cs_dsp_create_name(dsp);
2198         if (ret)
2199                 return ret;
2200
2201         INIT_LIST_HEAD(&dsp->alg_regions);
2202         INIT_LIST_HEAD(&dsp->ctl_list);
2203
2204         mutex_init(&dsp->pwr_lock);
2205
2206         return 0;
2207 }
2208
2209 /**
2210  * cs_dsp_adsp1_init() - Initialise a cs_dsp structure representing a ADSP1 device
2211  * @dsp: pointer to DSP structure
2212  *
2213  * Return: Zero for success, a negative number on error.
2214  */
2215 int cs_dsp_adsp1_init(struct cs_dsp *dsp)
2216 {
2217         dsp->ops = &cs_dsp_adsp1_ops;
2218
2219         return cs_dsp_common_init(dsp);
2220 }
2221 EXPORT_SYMBOL_GPL(cs_dsp_adsp1_init);
2222
2223 /**
2224  * cs_dsp_adsp1_power_up() - Load and start the named firmware
2225  * @dsp: pointer to DSP structure
2226  * @wmfw_firmware: the firmware to be sent
2227  * @wmfw_filename: file name of firmware to be sent
2228  * @coeff_firmware: the coefficient data to be sent
2229  * @coeff_filename: file name of coefficient to data be sent
2230  * @fw_name: the user-friendly firmware name
2231  *
2232  * Return: Zero for success, a negative number on error.
2233  */
2234 int cs_dsp_adsp1_power_up(struct cs_dsp *dsp,
2235                           const struct firmware *wmfw_firmware, char *wmfw_filename,
2236                           const struct firmware *coeff_firmware, char *coeff_filename,
2237                           const char *fw_name)
2238 {
2239         unsigned int val;
2240         int ret;
2241
2242         mutex_lock(&dsp->pwr_lock);
2243
2244         dsp->fw_name = fw_name;
2245
2246         regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
2247                            ADSP1_SYS_ENA, ADSP1_SYS_ENA);
2248
2249         /*
2250          * For simplicity set the DSP clock rate to be the
2251          * SYSCLK rate rather than making it configurable.
2252          */
2253         if (dsp->sysclk_reg) {
2254                 ret = regmap_read(dsp->regmap, dsp->sysclk_reg, &val);
2255                 if (ret != 0) {
2256                         cs_dsp_err(dsp, "Failed to read SYSCLK state: %d\n", ret);
2257                         goto err_mutex;
2258                 }
2259
2260                 val = (val & dsp->sysclk_mask) >> dsp->sysclk_shift;
2261
2262                 ret = regmap_update_bits(dsp->regmap,
2263                                          dsp->base + ADSP1_CONTROL_31,
2264                                          ADSP1_CLK_SEL_MASK, val);
2265                 if (ret != 0) {
2266                         cs_dsp_err(dsp, "Failed to set clock rate: %d\n", ret);
2267                         goto err_mutex;
2268                 }
2269         }
2270
2271         ret = cs_dsp_load(dsp, wmfw_firmware, wmfw_filename);
2272         if (ret != 0)
2273                 goto err_ena;
2274
2275         ret = cs_dsp_adsp1_setup_algs(dsp);
2276         if (ret != 0)
2277                 goto err_ena;
2278
2279         ret = cs_dsp_load_coeff(dsp, coeff_firmware, coeff_filename);
2280         if (ret != 0)
2281                 goto err_ena;
2282
2283         /* Initialize caches for enabled and unset controls */
2284         ret = cs_dsp_coeff_init_control_caches(dsp);
2285         if (ret != 0)
2286                 goto err_ena;
2287
2288         /* Sync set controls */
2289         ret = cs_dsp_coeff_sync_controls(dsp);
2290         if (ret != 0)
2291                 goto err_ena;
2292
2293         dsp->booted = true;
2294
2295         /* Start the core running */
2296         regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
2297                            ADSP1_CORE_ENA | ADSP1_START,
2298                            ADSP1_CORE_ENA | ADSP1_START);
2299
2300         dsp->running = true;
2301
2302         mutex_unlock(&dsp->pwr_lock);
2303
2304         return 0;
2305
2306 err_ena:
2307         regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
2308                            ADSP1_SYS_ENA, 0);
2309 err_mutex:
2310         mutex_unlock(&dsp->pwr_lock);
2311         return ret;
2312 }
2313 EXPORT_SYMBOL_GPL(cs_dsp_adsp1_power_up);
2314
2315 /**
2316  * cs_dsp_adsp1_power_down() - Halts the DSP
2317  * @dsp: pointer to DSP structure
2318  */
2319 void cs_dsp_adsp1_power_down(struct cs_dsp *dsp)
2320 {
2321         struct cs_dsp_coeff_ctl *ctl;
2322
2323         mutex_lock(&dsp->pwr_lock);
2324
2325         dsp->running = false;
2326         dsp->booted = false;
2327
2328         /* Halt the core */
2329         regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
2330                            ADSP1_CORE_ENA | ADSP1_START, 0);
2331
2332         regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_19,
2333                            ADSP1_WDMA_BUFFER_LENGTH_MASK, 0);
2334
2335         regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30,
2336                            ADSP1_SYS_ENA, 0);
2337
2338         list_for_each_entry(ctl, &dsp->ctl_list, list)
2339                 ctl->enabled = 0;
2340
2341         cs_dsp_free_alg_regions(dsp);
2342
2343         mutex_unlock(&dsp->pwr_lock);
2344 }
2345 EXPORT_SYMBOL_GPL(cs_dsp_adsp1_power_down);
2346
2347 static int cs_dsp_adsp2v2_enable_core(struct cs_dsp *dsp)
2348 {
2349         unsigned int val;
2350         int ret, count;
2351
2352         /* Wait for the RAM to start, should be near instantaneous */
2353         for (count = 0; count < 10; ++count) {
2354                 ret = regmap_read(dsp->regmap, dsp->base + ADSP2_STATUS1, &val);
2355                 if (ret != 0)
2356                         return ret;
2357
2358                 if (val & ADSP2_RAM_RDY)
2359                         break;
2360
2361                 usleep_range(250, 500);
2362         }
2363
2364         if (!(val & ADSP2_RAM_RDY)) {
2365                 cs_dsp_err(dsp, "Failed to start DSP RAM\n");
2366                 return -EBUSY;
2367         }
2368
2369         cs_dsp_dbg(dsp, "RAM ready after %d polls\n", count);
2370
2371         return 0;
2372 }
2373
2374 static int cs_dsp_adsp2_enable_core(struct cs_dsp *dsp)
2375 {
2376         int ret;
2377
2378         ret = regmap_update_bits_async(dsp->regmap, dsp->base + ADSP2_CONTROL,
2379                                        ADSP2_SYS_ENA, ADSP2_SYS_ENA);
2380         if (ret != 0)
2381                 return ret;
2382
2383         return cs_dsp_adsp2v2_enable_core(dsp);
2384 }
2385
2386 static int cs_dsp_adsp2_lock(struct cs_dsp *dsp, unsigned int lock_regions)
2387 {
2388         struct regmap *regmap = dsp->regmap;
2389         unsigned int code0, code1, lock_reg;
2390
2391         if (!(lock_regions & CS_ADSP2_REGION_ALL))
2392                 return 0;
2393
2394         lock_regions &= CS_ADSP2_REGION_ALL;
2395         lock_reg = dsp->base + ADSP2_LOCK_REGION_1_LOCK_REGION_0;
2396
2397         while (lock_regions) {
2398                 code0 = code1 = 0;
2399                 if (lock_regions & BIT(0)) {
2400                         code0 = ADSP2_LOCK_CODE_0;
2401                         code1 = ADSP2_LOCK_CODE_1;
2402                 }
2403                 if (lock_regions & BIT(1)) {
2404                         code0 |= ADSP2_LOCK_CODE_0 << ADSP2_LOCK_REGION_SHIFT;
2405                         code1 |= ADSP2_LOCK_CODE_1 << ADSP2_LOCK_REGION_SHIFT;
2406                 }
2407                 regmap_write(regmap, lock_reg, code0);
2408                 regmap_write(regmap, lock_reg, code1);
2409                 lock_regions >>= 2;
2410                 lock_reg += 2;
2411         }
2412
2413         return 0;
2414 }
2415
2416 static int cs_dsp_adsp2_enable_memory(struct cs_dsp *dsp)
2417 {
2418         return regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
2419                                   ADSP2_MEM_ENA, ADSP2_MEM_ENA);
2420 }
2421
2422 static void cs_dsp_adsp2_disable_memory(struct cs_dsp *dsp)
2423 {
2424         regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
2425                            ADSP2_MEM_ENA, 0);
2426 }
2427
2428 static void cs_dsp_adsp2_disable_core(struct cs_dsp *dsp)
2429 {
2430         regmap_write(dsp->regmap, dsp->base + ADSP2_RDMA_CONFIG_1, 0);
2431         regmap_write(dsp->regmap, dsp->base + ADSP2_WDMA_CONFIG_1, 0);
2432         regmap_write(dsp->regmap, dsp->base + ADSP2_WDMA_CONFIG_2, 0);
2433
2434         regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
2435                            ADSP2_SYS_ENA, 0);
2436 }
2437
2438 static void cs_dsp_adsp2v2_disable_core(struct cs_dsp *dsp)
2439 {
2440         regmap_write(dsp->regmap, dsp->base + ADSP2_RDMA_CONFIG_1, 0);
2441         regmap_write(dsp->regmap, dsp->base + ADSP2_WDMA_CONFIG_1, 0);
2442         regmap_write(dsp->regmap, dsp->base + ADSP2V2_WDMA_CONFIG_2, 0);
2443 }
2444
2445 static int cs_dsp_halo_configure_mpu(struct cs_dsp *dsp, unsigned int lock_regions)
2446 {
2447         struct reg_sequence config[] = {
2448                 { dsp->base + HALO_MPU_LOCK_CONFIG,     0x5555 },
2449                 { dsp->base + HALO_MPU_LOCK_CONFIG,     0xAAAA },
2450                 { dsp->base + HALO_MPU_XMEM_ACCESS_0,   0xFFFFFFFF },
2451                 { dsp->base + HALO_MPU_YMEM_ACCESS_0,   0xFFFFFFFF },
2452                 { dsp->base + HALO_MPU_WINDOW_ACCESS_0, lock_regions },
2453                 { dsp->base + HALO_MPU_XREG_ACCESS_0,   lock_regions },
2454                 { dsp->base + HALO_MPU_YREG_ACCESS_0,   lock_regions },
2455                 { dsp->base + HALO_MPU_XMEM_ACCESS_1,   0xFFFFFFFF },
2456                 { dsp->base + HALO_MPU_YMEM_ACCESS_1,   0xFFFFFFFF },
2457                 { dsp->base + HALO_MPU_WINDOW_ACCESS_1, lock_regions },
2458                 { dsp->base + HALO_MPU_XREG_ACCESS_1,   lock_regions },
2459                 { dsp->base + HALO_MPU_YREG_ACCESS_1,   lock_regions },
2460                 { dsp->base + HALO_MPU_XMEM_ACCESS_2,   0xFFFFFFFF },
2461                 { dsp->base + HALO_MPU_YMEM_ACCESS_2,   0xFFFFFFFF },
2462                 { dsp->base + HALO_MPU_WINDOW_ACCESS_2, lock_regions },
2463                 { dsp->base + HALO_MPU_XREG_ACCESS_2,   lock_regions },
2464                 { dsp->base + HALO_MPU_YREG_ACCESS_2,   lock_regions },
2465                 { dsp->base + HALO_MPU_XMEM_ACCESS_3,   0xFFFFFFFF },
2466                 { dsp->base + HALO_MPU_YMEM_ACCESS_3,   0xFFFFFFFF },
2467                 { dsp->base + HALO_MPU_WINDOW_ACCESS_3, lock_regions },
2468                 { dsp->base + HALO_MPU_XREG_ACCESS_3,   lock_regions },
2469                 { dsp->base + HALO_MPU_YREG_ACCESS_3,   lock_regions },
2470                 { dsp->base + HALO_MPU_LOCK_CONFIG,     0 },
2471         };
2472
2473         return regmap_multi_reg_write(dsp->regmap, config, ARRAY_SIZE(config));
2474 }
2475
2476 /**
2477  * cs_dsp_set_dspclk() - Applies the given frequency to the given cs_dsp
2478  * @dsp: pointer to DSP structure
2479  * @freq: clock rate to set
2480  *
2481  * This is only for use on ADSP2 cores.
2482  *
2483  * Return: Zero for success, a negative number on error.
2484  */
2485 int cs_dsp_set_dspclk(struct cs_dsp *dsp, unsigned int freq)
2486 {
2487         int ret;
2488
2489         ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CLOCKING,
2490                                  ADSP2_CLK_SEL_MASK,
2491                                  freq << ADSP2_CLK_SEL_SHIFT);
2492         if (ret)
2493                 cs_dsp_err(dsp, "Failed to set clock rate: %d\n", ret);
2494
2495         return ret;
2496 }
2497 EXPORT_SYMBOL_GPL(cs_dsp_set_dspclk);
2498
2499 static void cs_dsp_stop_watchdog(struct cs_dsp *dsp)
2500 {
2501         regmap_update_bits(dsp->regmap, dsp->base + ADSP2_WATCHDOG,
2502                            ADSP2_WDT_ENA_MASK, 0);
2503 }
2504
2505 static void cs_dsp_halo_stop_watchdog(struct cs_dsp *dsp)
2506 {
2507         regmap_update_bits(dsp->regmap, dsp->base + HALO_WDT_CONTROL,
2508                            HALO_WDT_EN_MASK, 0);
2509 }
2510
2511 /**
2512  * cs_dsp_power_up() - Downloads firmware to the DSP
2513  * @dsp: pointer to DSP structure
2514  * @wmfw_firmware: the firmware to be sent
2515  * @wmfw_filename: file name of firmware to be sent
2516  * @coeff_firmware: the coefficient data to be sent
2517  * @coeff_filename: file name of coefficient to data be sent
2518  * @fw_name: the user-friendly firmware name
2519  *
2520  * This function is used on ADSP2 and Halo DSP cores, it powers-up the DSP core
2521  * and downloads the firmware but does not start the firmware running. The
2522  * cs_dsp booted flag will be set once completed and if the core has a low-power
2523  * memory retention mode it will be put into this state after the firmware is
2524  * downloaded.
2525  *
2526  * Return: Zero for success, a negative number on error.
2527  */
2528 int cs_dsp_power_up(struct cs_dsp *dsp,
2529                     const struct firmware *wmfw_firmware, char *wmfw_filename,
2530                     const struct firmware *coeff_firmware, char *coeff_filename,
2531                     const char *fw_name)
2532 {
2533         int ret;
2534
2535         mutex_lock(&dsp->pwr_lock);
2536
2537         dsp->fw_name = fw_name;
2538
2539         if (dsp->ops->enable_memory) {
2540                 ret = dsp->ops->enable_memory(dsp);
2541                 if (ret != 0)
2542                         goto err_mutex;
2543         }
2544
2545         if (dsp->ops->enable_core) {
2546                 ret = dsp->ops->enable_core(dsp);
2547                 if (ret != 0)
2548                         goto err_mem;
2549         }
2550
2551         ret = cs_dsp_load(dsp, wmfw_firmware, wmfw_filename);
2552         if (ret != 0)
2553                 goto err_ena;
2554
2555         ret = dsp->ops->setup_algs(dsp);
2556         if (ret != 0)
2557                 goto err_ena;
2558
2559         ret = cs_dsp_load_coeff(dsp, coeff_firmware, coeff_filename);
2560         if (ret != 0)
2561                 goto err_ena;
2562
2563         /* Initialize caches for enabled and unset controls */
2564         ret = cs_dsp_coeff_init_control_caches(dsp);
2565         if (ret != 0)
2566                 goto err_ena;
2567
2568         if (dsp->ops->disable_core)
2569                 dsp->ops->disable_core(dsp);
2570
2571         dsp->booted = true;
2572
2573         mutex_unlock(&dsp->pwr_lock);
2574
2575         return 0;
2576 err_ena:
2577         if (dsp->ops->disable_core)
2578                 dsp->ops->disable_core(dsp);
2579 err_mem:
2580         if (dsp->ops->disable_memory)
2581                 dsp->ops->disable_memory(dsp);
2582 err_mutex:
2583         mutex_unlock(&dsp->pwr_lock);
2584
2585         return ret;
2586 }
2587 EXPORT_SYMBOL_GPL(cs_dsp_power_up);
2588
2589 /**
2590  * cs_dsp_power_down() - Powers-down the DSP
2591  * @dsp: pointer to DSP structure
2592  *
2593  * cs_dsp_stop() must have been called before this function. The core will be
2594  * fully powered down and so the memory will not be retained.
2595  */
2596 void cs_dsp_power_down(struct cs_dsp *dsp)
2597 {
2598         struct cs_dsp_coeff_ctl *ctl;
2599
2600         mutex_lock(&dsp->pwr_lock);
2601
2602         cs_dsp_debugfs_clear(dsp);
2603
2604         dsp->fw_id = 0;
2605         dsp->fw_id_version = 0;
2606
2607         dsp->booted = false;
2608
2609         if (dsp->ops->disable_memory)
2610                 dsp->ops->disable_memory(dsp);
2611
2612         list_for_each_entry(ctl, &dsp->ctl_list, list)
2613                 ctl->enabled = 0;
2614
2615         cs_dsp_free_alg_regions(dsp);
2616
2617         mutex_unlock(&dsp->pwr_lock);
2618
2619         cs_dsp_dbg(dsp, "Shutdown complete\n");
2620 }
2621 EXPORT_SYMBOL_GPL(cs_dsp_power_down);
2622
2623 static int cs_dsp_adsp2_start_core(struct cs_dsp *dsp)
2624 {
2625         return regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
2626                                   ADSP2_CORE_ENA | ADSP2_START,
2627                                   ADSP2_CORE_ENA | ADSP2_START);
2628 }
2629
2630 static void cs_dsp_adsp2_stop_core(struct cs_dsp *dsp)
2631 {
2632         regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
2633                            ADSP2_CORE_ENA | ADSP2_START, 0);
2634 }
2635
2636 /**
2637  * cs_dsp_run() - Starts the firmware running
2638  * @dsp: pointer to DSP structure
2639  *
2640  * cs_dsp_power_up() must have previously been called successfully.
2641  *
2642  * Return: Zero for success, a negative number on error.
2643  */
2644 int cs_dsp_run(struct cs_dsp *dsp)
2645 {
2646         int ret;
2647
2648         mutex_lock(&dsp->pwr_lock);
2649
2650         if (!dsp->booted) {
2651                 ret = -EIO;
2652                 goto err;
2653         }
2654
2655         if (dsp->ops->enable_core) {
2656                 ret = dsp->ops->enable_core(dsp);
2657                 if (ret != 0)
2658                         goto err;
2659         }
2660
2661         if (dsp->client_ops->pre_run) {
2662                 ret = dsp->client_ops->pre_run(dsp);
2663                 if (ret)
2664                         goto err;
2665         }
2666
2667         /* Sync set controls */
2668         ret = cs_dsp_coeff_sync_controls(dsp);
2669         if (ret != 0)
2670                 goto err;
2671
2672         if (dsp->ops->lock_memory) {
2673                 ret = dsp->ops->lock_memory(dsp, dsp->lock_regions);
2674                 if (ret != 0) {
2675                         cs_dsp_err(dsp, "Error configuring MPU: %d\n", ret);
2676                         goto err;
2677                 }
2678         }
2679
2680         if (dsp->ops->start_core) {
2681                 ret = dsp->ops->start_core(dsp);
2682                 if (ret != 0)
2683                         goto err;
2684         }
2685
2686         dsp->running = true;
2687
2688         if (dsp->client_ops->post_run) {
2689                 ret = dsp->client_ops->post_run(dsp);
2690                 if (ret)
2691                         goto err;
2692         }
2693
2694         mutex_unlock(&dsp->pwr_lock);
2695
2696         return 0;
2697
2698 err:
2699         if (dsp->ops->stop_core)
2700                 dsp->ops->stop_core(dsp);
2701         if (dsp->ops->disable_core)
2702                 dsp->ops->disable_core(dsp);
2703         mutex_unlock(&dsp->pwr_lock);
2704
2705         return ret;
2706 }
2707 EXPORT_SYMBOL_GPL(cs_dsp_run);
2708
2709 /**
2710  * cs_dsp_stop() - Stops the firmware
2711  * @dsp: pointer to DSP structure
2712  *
2713  * Memory will not be disabled so firmware will remain loaded.
2714  */
2715 void cs_dsp_stop(struct cs_dsp *dsp)
2716 {
2717         /* Tell the firmware to cleanup */
2718         cs_dsp_signal_event_controls(dsp, CS_DSP_FW_EVENT_SHUTDOWN);
2719
2720         if (dsp->ops->stop_watchdog)
2721                 dsp->ops->stop_watchdog(dsp);
2722
2723         /* Log firmware state, it can be useful for analysis */
2724         if (dsp->ops->show_fw_status)
2725                 dsp->ops->show_fw_status(dsp);
2726
2727         mutex_lock(&dsp->pwr_lock);
2728
2729         dsp->running = false;
2730
2731         if (dsp->ops->stop_core)
2732                 dsp->ops->stop_core(dsp);
2733         if (dsp->ops->disable_core)
2734                 dsp->ops->disable_core(dsp);
2735
2736         if (dsp->client_ops->post_stop)
2737                 dsp->client_ops->post_stop(dsp);
2738
2739         mutex_unlock(&dsp->pwr_lock);
2740
2741         cs_dsp_dbg(dsp, "Execution stopped\n");
2742 }
2743 EXPORT_SYMBOL_GPL(cs_dsp_stop);
2744
2745 static int cs_dsp_halo_start_core(struct cs_dsp *dsp)
2746 {
2747         int ret;
2748
2749         ret = regmap_update_bits(dsp->regmap, dsp->base + HALO_CCM_CORE_CONTROL,
2750                                  HALO_CORE_RESET | HALO_CORE_EN,
2751                                  HALO_CORE_RESET | HALO_CORE_EN);
2752         if (ret)
2753                 return ret;
2754
2755         return regmap_update_bits(dsp->regmap, dsp->base + HALO_CCM_CORE_CONTROL,
2756                                   HALO_CORE_RESET, 0);
2757 }
2758
2759 static void cs_dsp_halo_stop_core(struct cs_dsp *dsp)
2760 {
2761         regmap_update_bits(dsp->regmap, dsp->base + HALO_CCM_CORE_CONTROL,
2762                            HALO_CORE_EN, 0);
2763
2764         /* reset halo core with CORE_SOFT_RESET */
2765         regmap_update_bits(dsp->regmap, dsp->base + HALO_CORE_SOFT_RESET,
2766                            HALO_CORE_SOFT_RESET_MASK, 1);
2767 }
2768
2769 /**
2770  * cs_dsp_adsp2_init() - Initialise a cs_dsp structure representing a ADSP2 core
2771  * @dsp: pointer to DSP structure
2772  *
2773  * Return: Zero for success, a negative number on error.
2774  */
2775 int cs_dsp_adsp2_init(struct cs_dsp *dsp)
2776 {
2777         int ret;
2778
2779         switch (dsp->rev) {
2780         case 0:
2781                 /*
2782                  * Disable the DSP memory by default when in reset for a small
2783                  * power saving.
2784                  */
2785                 ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
2786                                          ADSP2_MEM_ENA, 0);
2787                 if (ret) {
2788                         cs_dsp_err(dsp,
2789                                    "Failed to clear memory retention: %d\n", ret);
2790                         return ret;
2791                 }
2792
2793                 dsp->ops = &cs_dsp_adsp2_ops[0];
2794                 break;
2795         case 1:
2796                 dsp->ops = &cs_dsp_adsp2_ops[1];
2797                 break;
2798         default:
2799                 dsp->ops = &cs_dsp_adsp2_ops[2];
2800                 break;
2801         }
2802
2803         return cs_dsp_common_init(dsp);
2804 }
2805 EXPORT_SYMBOL_GPL(cs_dsp_adsp2_init);
2806
2807 /**
2808  * cs_dsp_halo_init() - Initialise a cs_dsp structure representing a HALO Core DSP
2809  * @dsp: pointer to DSP structure
2810  *
2811  * Return: Zero for success, a negative number on error.
2812  */
2813 int cs_dsp_halo_init(struct cs_dsp *dsp)
2814 {
2815         dsp->ops = &cs_dsp_halo_ops;
2816
2817         return cs_dsp_common_init(dsp);
2818 }
2819 EXPORT_SYMBOL_GPL(cs_dsp_halo_init);
2820
2821 /**
2822  * cs_dsp_remove() - Clean a cs_dsp before deletion
2823  * @dsp: pointer to DSP structure
2824  */
2825 void cs_dsp_remove(struct cs_dsp *dsp)
2826 {
2827         struct cs_dsp_coeff_ctl *ctl;
2828
2829         while (!list_empty(&dsp->ctl_list)) {
2830                 ctl = list_first_entry(&dsp->ctl_list, struct cs_dsp_coeff_ctl, list);
2831
2832                 if (dsp->client_ops->control_remove)
2833                         dsp->client_ops->control_remove(ctl);
2834
2835                 list_del(&ctl->list);
2836                 cs_dsp_free_ctl_blk(ctl);
2837         }
2838 }
2839 EXPORT_SYMBOL_GPL(cs_dsp_remove);
2840
2841 /**
2842  * cs_dsp_read_raw_data_block() - Reads a block of data from DSP memory
2843  * @dsp: pointer to DSP structure
2844  * @mem_type: the type of DSP memory containing the data to be read
2845  * @mem_addr: the address of the data within the memory region
2846  * @num_words: the length of the data to read
2847  * @data: a buffer to store the fetched data
2848  *
2849  * If this is used to read unpacked 24-bit memory, each 24-bit DSP word will
2850  * occupy 32-bits in data (MSbyte will be 0). This padding can be removed using
2851  * cs_dsp_remove_padding()
2852  *
2853  * Return: Zero for success, a negative number on error.
2854  */
2855 int cs_dsp_read_raw_data_block(struct cs_dsp *dsp, int mem_type, unsigned int mem_addr,
2856                                unsigned int num_words, __be32 *data)
2857 {
2858         struct cs_dsp_region const *mem = cs_dsp_find_region(dsp, mem_type);
2859         unsigned int reg;
2860         int ret;
2861
2862         lockdep_assert_held(&dsp->pwr_lock);
2863
2864         if (!mem)
2865                 return -EINVAL;
2866
2867         reg = dsp->ops->region_to_reg(mem, mem_addr);
2868
2869         ret = regmap_raw_read(dsp->regmap, reg, data,
2870                               sizeof(*data) * num_words);
2871         if (ret < 0)
2872                 return ret;
2873
2874         return 0;
2875 }
2876 EXPORT_SYMBOL_GPL(cs_dsp_read_raw_data_block);
2877
2878 /**
2879  * cs_dsp_read_data_word() - Reads a word from DSP memory
2880  * @dsp: pointer to DSP structure
2881  * @mem_type: the type of DSP memory containing the data to be read
2882  * @mem_addr: the address of the data within the memory region
2883  * @data: a buffer to store the fetched data
2884  *
2885  * Return: Zero for success, a negative number on error.
2886  */
2887 int cs_dsp_read_data_word(struct cs_dsp *dsp, int mem_type, unsigned int mem_addr, u32 *data)
2888 {
2889         __be32 raw;
2890         int ret;
2891
2892         ret = cs_dsp_read_raw_data_block(dsp, mem_type, mem_addr, 1, &raw);
2893         if (ret < 0)
2894                 return ret;
2895
2896         *data = be32_to_cpu(raw) & 0x00ffffffu;
2897
2898         return 0;
2899 }
2900 EXPORT_SYMBOL_GPL(cs_dsp_read_data_word);
2901
2902 /**
2903  * cs_dsp_write_data_word() - Writes a word to DSP memory
2904  * @dsp: pointer to DSP structure
2905  * @mem_type: the type of DSP memory containing the data to be written
2906  * @mem_addr: the address of the data within the memory region
2907  * @data: the data to be written
2908  *
2909  * Return: Zero for success, a negative number on error.
2910  */
2911 int cs_dsp_write_data_word(struct cs_dsp *dsp, int mem_type, unsigned int mem_addr, u32 data)
2912 {
2913         struct cs_dsp_region const *mem = cs_dsp_find_region(dsp, mem_type);
2914         __be32 val = cpu_to_be32(data & 0x00ffffffu);
2915         unsigned int reg;
2916
2917         lockdep_assert_held(&dsp->pwr_lock);
2918
2919         if (!mem)
2920                 return -EINVAL;
2921
2922         reg = dsp->ops->region_to_reg(mem, mem_addr);
2923
2924         return regmap_raw_write(dsp->regmap, reg, &val, sizeof(val));
2925 }
2926 EXPORT_SYMBOL_GPL(cs_dsp_write_data_word);
2927
2928 /**
2929  * cs_dsp_remove_padding() - Convert unpacked words to packed bytes
2930  * @buf: buffer containing DSP words read from DSP memory
2931  * @nwords: number of words to convert
2932  *
2933  * DSP words from the register map have pad bytes and the data bytes
2934  * are in swapped order. This swaps to the native endian order and
2935  * strips the pad bytes.
2936  */
2937 void cs_dsp_remove_padding(u32 *buf, int nwords)
2938 {
2939         const __be32 *pack_in = (__be32 *)buf;
2940         u8 *pack_out = (u8 *)buf;
2941         int i;
2942
2943         for (i = 0; i < nwords; i++) {
2944                 u32 word = be32_to_cpu(*pack_in++);
2945                 *pack_out++ = (u8)word;
2946                 *pack_out++ = (u8)(word >> 8);
2947                 *pack_out++ = (u8)(word >> 16);
2948         }
2949 }
2950 EXPORT_SYMBOL_GPL(cs_dsp_remove_padding);
2951
2952 /**
2953  * cs_dsp_adsp2_bus_error() - Handle a DSP bus error interrupt
2954  * @dsp: pointer to DSP structure
2955  *
2956  * The firmware and DSP state will be logged for future analysis.
2957  */
2958 void cs_dsp_adsp2_bus_error(struct cs_dsp *dsp)
2959 {
2960         unsigned int val;
2961         struct regmap *regmap = dsp->regmap;
2962         int ret = 0;
2963
2964         mutex_lock(&dsp->pwr_lock);
2965
2966         ret = regmap_read(regmap, dsp->base + ADSP2_LOCK_REGION_CTRL, &val);
2967         if (ret) {
2968                 cs_dsp_err(dsp,
2969                            "Failed to read Region Lock Ctrl register: %d\n", ret);
2970                 goto error;
2971         }
2972
2973         if (val & ADSP2_WDT_TIMEOUT_STS_MASK) {
2974                 cs_dsp_err(dsp, "watchdog timeout error\n");
2975                 dsp->ops->stop_watchdog(dsp);
2976                 if (dsp->client_ops->watchdog_expired)
2977                         dsp->client_ops->watchdog_expired(dsp);
2978         }
2979
2980         if (val & (ADSP2_ADDR_ERR_MASK | ADSP2_REGION_LOCK_ERR_MASK)) {
2981                 if (val & ADSP2_ADDR_ERR_MASK)
2982                         cs_dsp_err(dsp, "bus error: address error\n");
2983                 else
2984                         cs_dsp_err(dsp, "bus error: region lock error\n");
2985
2986                 ret = regmap_read(regmap, dsp->base + ADSP2_BUS_ERR_ADDR, &val);
2987                 if (ret) {
2988                         cs_dsp_err(dsp,
2989                                    "Failed to read Bus Err Addr register: %d\n",
2990                                    ret);
2991                         goto error;
2992                 }
2993
2994                 cs_dsp_err(dsp, "bus error address = 0x%x\n",
2995                            val & ADSP2_BUS_ERR_ADDR_MASK);
2996
2997                 ret = regmap_read(regmap,
2998                                   dsp->base + ADSP2_PMEM_ERR_ADDR_XMEM_ERR_ADDR,
2999                                   &val);
3000                 if (ret) {
3001                         cs_dsp_err(dsp,
3002                                    "Failed to read Pmem Xmem Err Addr register: %d\n",
3003                                    ret);
3004                         goto error;
3005                 }
3006
3007                 cs_dsp_err(dsp, "xmem error address = 0x%x\n",
3008                            val & ADSP2_XMEM_ERR_ADDR_MASK);
3009                 cs_dsp_err(dsp, "pmem error address = 0x%x\n",
3010                            (val & ADSP2_PMEM_ERR_ADDR_MASK) >>
3011                            ADSP2_PMEM_ERR_ADDR_SHIFT);
3012         }
3013
3014         regmap_update_bits(regmap, dsp->base + ADSP2_LOCK_REGION_CTRL,
3015                            ADSP2_CTRL_ERR_EINT, ADSP2_CTRL_ERR_EINT);
3016
3017 error:
3018         mutex_unlock(&dsp->pwr_lock);
3019 }
3020 EXPORT_SYMBOL_GPL(cs_dsp_adsp2_bus_error);
3021
3022 /**
3023  * cs_dsp_halo_bus_error() - Handle a DSP bus error interrupt
3024  * @dsp: pointer to DSP structure
3025  *
3026  * The firmware and DSP state will be logged for future analysis.
3027  */
3028 void cs_dsp_halo_bus_error(struct cs_dsp *dsp)
3029 {
3030         struct regmap *regmap = dsp->regmap;
3031         unsigned int fault[6];
3032         struct reg_sequence clear[] = {
3033                 { dsp->base + HALO_MPU_XM_VIO_STATUS,     0x0 },
3034                 { dsp->base + HALO_MPU_YM_VIO_STATUS,     0x0 },
3035                 { dsp->base + HALO_MPU_PM_VIO_STATUS,     0x0 },
3036         };
3037         int ret;
3038
3039         mutex_lock(&dsp->pwr_lock);
3040
3041         ret = regmap_read(regmap, dsp->base_sysinfo + HALO_AHBM_WINDOW_DEBUG_1,
3042                           fault);
3043         if (ret) {
3044                 cs_dsp_warn(dsp, "Failed to read AHB DEBUG_1: %d\n", ret);
3045                 goto exit_unlock;
3046         }
3047
3048         cs_dsp_warn(dsp, "AHB: STATUS: 0x%x ADDR: 0x%x\n",
3049                     *fault & HALO_AHBM_FLAGS_ERR_MASK,
3050                     (*fault & HALO_AHBM_CORE_ERR_ADDR_MASK) >>
3051                     HALO_AHBM_CORE_ERR_ADDR_SHIFT);
3052
3053         ret = regmap_read(regmap, dsp->base_sysinfo + HALO_AHBM_WINDOW_DEBUG_0,
3054                           fault);
3055         if (ret) {
3056                 cs_dsp_warn(dsp, "Failed to read AHB DEBUG_0: %d\n", ret);
3057                 goto exit_unlock;
3058         }
3059
3060         cs_dsp_warn(dsp, "AHB: SYS_ADDR: 0x%x\n", *fault);
3061
3062         ret = regmap_bulk_read(regmap, dsp->base + HALO_MPU_XM_VIO_ADDR,
3063                                fault, ARRAY_SIZE(fault));
3064         if (ret) {
3065                 cs_dsp_warn(dsp, "Failed to read MPU fault info: %d\n", ret);
3066                 goto exit_unlock;
3067         }
3068
3069         cs_dsp_warn(dsp, "XM: STATUS:0x%x ADDR:0x%x\n", fault[1], fault[0]);
3070         cs_dsp_warn(dsp, "YM: STATUS:0x%x ADDR:0x%x\n", fault[3], fault[2]);
3071         cs_dsp_warn(dsp, "PM: STATUS:0x%x ADDR:0x%x\n", fault[5], fault[4]);
3072
3073         ret = regmap_multi_reg_write(dsp->regmap, clear, ARRAY_SIZE(clear));
3074         if (ret)
3075                 cs_dsp_warn(dsp, "Failed to clear MPU status: %d\n", ret);
3076
3077 exit_unlock:
3078         mutex_unlock(&dsp->pwr_lock);
3079 }
3080 EXPORT_SYMBOL_GPL(cs_dsp_halo_bus_error);
3081
3082 /**
3083  * cs_dsp_halo_wdt_expire() - Handle DSP watchdog expiry
3084  * @dsp: pointer to DSP structure
3085  *
3086  * This is logged for future analysis.
3087  */
3088 void cs_dsp_halo_wdt_expire(struct cs_dsp *dsp)
3089 {
3090         mutex_lock(&dsp->pwr_lock);
3091
3092         cs_dsp_warn(dsp, "WDT Expiry Fault\n");
3093
3094         dsp->ops->stop_watchdog(dsp);
3095         if (dsp->client_ops->watchdog_expired)
3096                 dsp->client_ops->watchdog_expired(dsp);
3097
3098         mutex_unlock(&dsp->pwr_lock);
3099 }
3100 EXPORT_SYMBOL_GPL(cs_dsp_halo_wdt_expire);
3101
3102 static const struct cs_dsp_ops cs_dsp_adsp1_ops = {
3103         .validate_version = cs_dsp_validate_version,
3104         .parse_sizes = cs_dsp_adsp1_parse_sizes,
3105         .region_to_reg = cs_dsp_region_to_reg,
3106 };
3107
3108 static const struct cs_dsp_ops cs_dsp_adsp2_ops[] = {
3109         {
3110                 .parse_sizes = cs_dsp_adsp2_parse_sizes,
3111                 .validate_version = cs_dsp_validate_version,
3112                 .setup_algs = cs_dsp_adsp2_setup_algs,
3113                 .region_to_reg = cs_dsp_region_to_reg,
3114
3115                 .show_fw_status = cs_dsp_adsp2_show_fw_status,
3116
3117                 .enable_memory = cs_dsp_adsp2_enable_memory,
3118                 .disable_memory = cs_dsp_adsp2_disable_memory,
3119
3120                 .enable_core = cs_dsp_adsp2_enable_core,
3121                 .disable_core = cs_dsp_adsp2_disable_core,
3122
3123                 .start_core = cs_dsp_adsp2_start_core,
3124                 .stop_core = cs_dsp_adsp2_stop_core,
3125
3126         },
3127         {
3128                 .parse_sizes = cs_dsp_adsp2_parse_sizes,
3129                 .validate_version = cs_dsp_validate_version,
3130                 .setup_algs = cs_dsp_adsp2_setup_algs,
3131                 .region_to_reg = cs_dsp_region_to_reg,
3132
3133                 .show_fw_status = cs_dsp_adsp2v2_show_fw_status,
3134
3135                 .enable_memory = cs_dsp_adsp2_enable_memory,
3136                 .disable_memory = cs_dsp_adsp2_disable_memory,
3137                 .lock_memory = cs_dsp_adsp2_lock,
3138
3139                 .enable_core = cs_dsp_adsp2v2_enable_core,
3140                 .disable_core = cs_dsp_adsp2v2_disable_core,
3141
3142                 .start_core = cs_dsp_adsp2_start_core,
3143                 .stop_core = cs_dsp_adsp2_stop_core,
3144         },
3145         {
3146                 .parse_sizes = cs_dsp_adsp2_parse_sizes,
3147                 .validate_version = cs_dsp_validate_version,
3148                 .setup_algs = cs_dsp_adsp2_setup_algs,
3149                 .region_to_reg = cs_dsp_region_to_reg,
3150
3151                 .show_fw_status = cs_dsp_adsp2v2_show_fw_status,
3152                 .stop_watchdog = cs_dsp_stop_watchdog,
3153
3154                 .enable_memory = cs_dsp_adsp2_enable_memory,
3155                 .disable_memory = cs_dsp_adsp2_disable_memory,
3156                 .lock_memory = cs_dsp_adsp2_lock,
3157
3158                 .enable_core = cs_dsp_adsp2v2_enable_core,
3159                 .disable_core = cs_dsp_adsp2v2_disable_core,
3160
3161                 .start_core = cs_dsp_adsp2_start_core,
3162                 .stop_core = cs_dsp_adsp2_stop_core,
3163         },
3164 };
3165
3166 static const struct cs_dsp_ops cs_dsp_halo_ops = {
3167         .parse_sizes = cs_dsp_adsp2_parse_sizes,
3168         .validate_version = cs_dsp_halo_validate_version,
3169         .setup_algs = cs_dsp_halo_setup_algs,
3170         .region_to_reg = cs_dsp_halo_region_to_reg,
3171
3172         .show_fw_status = cs_dsp_halo_show_fw_status,
3173         .stop_watchdog = cs_dsp_halo_stop_watchdog,
3174
3175         .lock_memory = cs_dsp_halo_configure_mpu,
3176
3177         .start_core = cs_dsp_halo_start_core,
3178         .stop_core = cs_dsp_halo_stop_core,
3179 };
3180
3181 MODULE_DESCRIPTION("Cirrus Logic DSP Support");
3182 MODULE_AUTHOR("Simon Trimmer <simont@opensource.cirrus.com>");
3183 MODULE_LICENSE("GPL v2");