xref: /linux/include/linux/firmware/cirrus/cs_dsp.h (revision a8e7ef3cec99ba2487110e01d77a8a278593b3e9) !
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  * cs_dsp.h  --  Cirrus Logic DSP firmware support
4  *
5  * Based on sound/soc/codecs/wm_adsp.h
6  *
7  * Copyright 2012 Wolfson Microelectronics plc
8  * Copyright (C) 2015-2021 Cirrus Logic, Inc. and
9  *                         Cirrus Logic International Semiconductor Ltd.
10  */
11 #ifndef __CS_DSP_H
12 #define __CS_DSP_H
13 
14 #include <linux/bits.h>
15 #include <linux/device.h>
16 #include <linux/firmware.h>
17 #include <linux/list.h>
18 #include <linux/regmap.h>
19 
20 #define CS_ADSP2_REGION_0 BIT(0)
21 #define CS_ADSP2_REGION_1 BIT(1)
22 #define CS_ADSP2_REGION_2 BIT(2)
23 #define CS_ADSP2_REGION_3 BIT(3)
24 #define CS_ADSP2_REGION_4 BIT(4)
25 #define CS_ADSP2_REGION_5 BIT(5)
26 #define CS_ADSP2_REGION_6 BIT(6)
27 #define CS_ADSP2_REGION_7 BIT(7)
28 #define CS_ADSP2_REGION_8 BIT(8)
29 #define CS_ADSP2_REGION_9 BIT(9)
30 #define CS_ADSP2_REGION_1_9 (CS_ADSP2_REGION_1 | \
31 		CS_ADSP2_REGION_2 | CS_ADSP2_REGION_3 | \
32 		CS_ADSP2_REGION_4 | CS_ADSP2_REGION_5 | \
33 		CS_ADSP2_REGION_6 | CS_ADSP2_REGION_7 | \
34 		CS_ADSP2_REGION_8 | CS_ADSP2_REGION_9)
35 #define CS_ADSP2_REGION_ALL (CS_ADSP2_REGION_0 | CS_ADSP2_REGION_1_9)
36 
37 #define CS_DSP_DATA_WORD_SIZE                3
38 #define CS_DSP_DATA_WORD_BITS                (3 * BITS_PER_BYTE)
39 
40 #define CS_DSP_ACKED_CTL_TIMEOUT_MS          100
41 #define CS_DSP_ACKED_CTL_N_QUICKPOLLS        10
42 #define CS_DSP_ACKED_CTL_MIN_VALUE           0
43 #define CS_DSP_ACKED_CTL_MAX_VALUE           0xFFFFFF
44 
45 /*
46  * Write sequence operation codes
47  */
48 #define CS_DSP_WSEQ_FULL	0x00
49 #define CS_DSP_WSEQ_ADDR8	0x02
50 #define CS_DSP_WSEQ_L16		0x04
51 #define CS_DSP_WSEQ_H16		0x05
52 #define CS_DSP_WSEQ_UNLOCK	0xFD
53 #define CS_DSP_WSEQ_END		0xFF
54 
55 /**
56  * struct cs_dsp_region - Describes a logical memory region in DSP address space
57  * @type:	Memory region type
58  * @base:	Address of region
59  */
60 struct cs_dsp_region {
61 	int type;
62 	unsigned int base;
63 };
64 
65 /**
66  * struct cs_dsp_alg_region - Describes a logical algorithm region in DSP address space
67  * @alg:	Algorithm id
68  * @ver:	Expected algorithm version
69  * @type:	Memory region type
70  * @base:	Address of region
71  */
72 struct cs_dsp_alg_region {
73 	unsigned int alg;
74 	unsigned int ver;
75 	int type;
76 	unsigned int base;
77 };
78 
79 /**
80  * struct cs_dsp_coeff_ctl - Describes a coefficient control
81  * @list:		List node for internal use
82  * @dsp:		DSP instance associated with this control
83  * @cache:		Cached value of the control
84  * @fw_name:		Name of the firmware
85  * @subname:		Name of the control parsed from the WMFW
86  * @subname_len:	Length of subname
87  * @offset:		Offset of control within alg_region in words
88  * @len:		Length of the cached value in bytes
89  * @type:		One of the WMFW_CTL_TYPE_ control types defined in wmfw.h
90  * @flags:		Bitfield of WMFW_CTL_FLAG_ control flags defined in wmfw.h
91  * @set:		Flag indicating the value has been written by the user
92  * @enabled:		Flag indicating whether control is enabled
93  * @alg_region:		Logical region associated with this control
94  * @priv:		For use by the client
95  */
96 struct cs_dsp_coeff_ctl {
97 	struct list_head list;
98 	struct cs_dsp *dsp;
99 	void *cache;
100 	const char *fw_name;
101 	/* Subname is needed to match with firmware */
102 	const char *subname;
103 	unsigned int subname_len;
104 	unsigned int offset;
105 	unsigned int len;
106 	unsigned int type;
107 	unsigned int flags;
108 	unsigned int set:1;
109 	unsigned int enabled:1;
110 	struct cs_dsp_alg_region alg_region;
111 
112 	void *priv;
113 };
114 
115 struct cs_dsp_ops;
116 struct cs_dsp_client_ops;
117 
118 /**
119  * struct cs_dsp - Configuration and state of a Cirrus Logic DSP
120  * @name:		The name of the DSP instance
121  * @rev:		Revision of the DSP
122  * @num:		DSP instance number
123  * @type:		Type of DSP
124  * @dev:		Driver model representation of the device
125  * @regmap:		Register map of the device
126  * @ops:		Function pointers for internal callbacks
127  * @client_ops:		Function pointers for client callbacks
128  * @base:		Address of the DSP registers
129  * @base_sysinfo:	Address of the sysinfo register (Halo only)
130  * @sysclk_reg:		Address of the sysclk register (ADSP1 only)
131  * @sysclk_mask:	Mask of frequency bits within sysclk register (ADSP1 only)
132  * @sysclk_shift:	Shift of frequency bits within sysclk register (ADSP1 only)
133  * @alg_regions:	List of currently loaded algorithm regions
134  * @fw_name:		Name of the current firmware
135  * @fw_id:		ID of the current firmware, obtained from the wmfw
136  * @fw_id_version:	Version of the firmware, obtained from the wmfw
137  * @fw_vendor_id:	Vendor of the firmware, obtained from the wmfw
138  * @mem:		DSP memory region descriptions
139  * @num_mems:		Number of memory regions in this DSP
140  * @fw_ver:		Version of the wmfw file format
141  * @booted:		Flag indicating DSP has been configured
142  * @running:		Flag indicating DSP is executing firmware
143  * @ctl_list:		Controls defined within the loaded DSP firmware
144  * @lock_regions:	Enable MPU traps on specified memory regions
145  * @pwr_lock:		Lock used to serialize accesses
146  * @debugfs_root:	Debugfs directory for this DSP instance
147  * @wmfw_file_name:	Filename of the currently loaded firmware
148  * @bin_file_name:	Filename of the currently loaded coefficients
149  */
150 struct cs_dsp {
151 	const char *name;
152 	int rev;
153 	int num;
154 	int type;
155 	struct device *dev;
156 	struct regmap *regmap;
157 
158 	const struct cs_dsp_ops *ops;
159 	const struct cs_dsp_client_ops *client_ops;
160 
161 	unsigned int base;
162 	unsigned int base_sysinfo;
163 	unsigned int sysclk_reg;
164 	unsigned int sysclk_mask;
165 	unsigned int sysclk_shift;
166 	bool no_core_startstop;
167 
168 	struct list_head alg_regions;
169 
170 	const char *fw_name;
171 	unsigned int fw_id;
172 	unsigned int fw_id_version;
173 	unsigned int fw_vendor_id;
174 
175 	const struct cs_dsp_region *mem;
176 	int num_mems;
177 
178 	int wmfw_ver;
179 
180 	bool booted;
181 	bool running;
182 	bool hibernating;
183 
184 	struct list_head ctl_list;
185 
186 	struct mutex pwr_lock;
187 
188 	unsigned int lock_regions;
189 
190 #ifdef CONFIG_DEBUG_FS
191 	struct dentry *debugfs_root;
192 	const char *wmfw_file_name;
193 	const char *bin_file_name;
194 #endif
195 };
196 
197 /**
198  * struct cs_dsp_client_ops - client callbacks
199  * @control_add:	Called under the pwr_lock when a control is created
200  * @control_remove:	Called under the pwr_lock when a control is destroyed
201  * @pre_run:		Called under the pwr_lock by cs_dsp_run() before the core is started
202  * @post_run:		Called under the pwr_lock by cs_dsp_run() after the core is started
203  * @pre_stop:		Called under the pwr_lock by cs_dsp_stop() before the core is stopped
204  * @post_stop:		Called under the pwr_lock by cs_dsp_stop() after the core is stopped
205  * @watchdog_expired:	Called when a watchdog expiry is detected
206  *
207  * These callbacks give the cs_dsp client an opportunity to respond to events
208  * or to perform actions atomically.
209  */
210 struct cs_dsp_client_ops {
211 	int (*control_add)(struct cs_dsp_coeff_ctl *ctl);
212 	void (*control_remove)(struct cs_dsp_coeff_ctl *ctl);
213 	int (*pre_run)(struct cs_dsp *dsp);
214 	int (*post_run)(struct cs_dsp *dsp);
215 	void (*pre_stop)(struct cs_dsp *dsp);
216 	void (*post_stop)(struct cs_dsp *dsp);
217 	void (*watchdog_expired)(struct cs_dsp *dsp);
218 };
219 
220 int cs_dsp_adsp1_init(struct cs_dsp *dsp);
221 int cs_dsp_adsp2_init(struct cs_dsp *dsp);
222 int cs_dsp_halo_init(struct cs_dsp *dsp);
223 
224 int cs_dsp_adsp1_power_up(struct cs_dsp *dsp,
225 			  const struct firmware *wmfw_firmware, const char *wmfw_filename,
226 			  const struct firmware *coeff_firmware, const char *coeff_filename,
227 			  const char *fw_name);
228 void cs_dsp_adsp1_power_down(struct cs_dsp *dsp);
229 int cs_dsp_power_up(struct cs_dsp *dsp,
230 		    const struct firmware *wmfw_firmware, const char *wmfw_filename,
231 		    const struct firmware *coeff_firmware, const char *coeff_filename,
232 		    const char *fw_name);
233 void cs_dsp_power_down(struct cs_dsp *dsp);
234 int cs_dsp_run(struct cs_dsp *dsp);
235 void cs_dsp_stop(struct cs_dsp *dsp);
236 
237 void cs_dsp_remove(struct cs_dsp *dsp);
238 
239 int cs_dsp_set_dspclk(struct cs_dsp *dsp, unsigned int freq);
240 void cs_dsp_adsp2_bus_error(struct cs_dsp *dsp);
241 void cs_dsp_halo_bus_error(struct cs_dsp *dsp);
242 void cs_dsp_halo_wdt_expire(struct cs_dsp *dsp);
243 
244 void cs_dsp_init_debugfs(struct cs_dsp *dsp, struct dentry *debugfs_root);
245 void cs_dsp_cleanup_debugfs(struct cs_dsp *dsp);
246 
247 int cs_dsp_coeff_write_acked_control(struct cs_dsp_coeff_ctl *ctl, unsigned int event_id);
248 int cs_dsp_coeff_write_ctrl(struct cs_dsp_coeff_ctl *ctl, unsigned int off,
249 			    const void *buf, size_t len);
250 int cs_dsp_coeff_lock_and_write_ctrl(struct cs_dsp_coeff_ctl *ctl, unsigned int off,
251 				     const void *buf, size_t len);
252 int cs_dsp_coeff_read_ctrl(struct cs_dsp_coeff_ctl *ctl, unsigned int off,
253 			   void *buf, size_t len);
254 int cs_dsp_coeff_lock_and_read_ctrl(struct cs_dsp_coeff_ctl *ctl, unsigned int off,
255 				    void *buf, size_t len);
256 struct cs_dsp_coeff_ctl *cs_dsp_get_ctl(struct cs_dsp *dsp, const char *name, int type,
257 					unsigned int alg);
258 
259 int cs_dsp_read_raw_data_block(struct cs_dsp *dsp, int mem_type, unsigned int mem_addr,
260 			       unsigned int num_words, __be32 *data);
261 int cs_dsp_read_data_word(struct cs_dsp *dsp, int mem_type, unsigned int mem_addr, u32 *data);
262 int cs_dsp_write_data_word(struct cs_dsp *dsp, int mem_type, unsigned int mem_addr, u32 data);
263 void cs_dsp_remove_padding(u32 *buf, int nwords);
264 
265 struct cs_dsp_alg_region *cs_dsp_find_alg_region(struct cs_dsp *dsp,
266 						 int type, unsigned int id);
267 
268 const char *cs_dsp_mem_region_name(unsigned int type);
269 
270 /**
271  * struct cs_dsp_wseq - Describes a write sequence
272  * @ctl:	Write sequence cs_dsp control
273  * @ops:	Operations contained within
274  */
275 struct cs_dsp_wseq {
276 	struct cs_dsp_coeff_ctl *ctl;
277 	struct list_head ops;
278 };
279 
280 int cs_dsp_wseq_init(struct cs_dsp *dsp, struct cs_dsp_wseq *wseqs, unsigned int num_wseqs);
281 int cs_dsp_wseq_write(struct cs_dsp *dsp, struct cs_dsp_wseq *wseq, u32 addr, u32 data,
282 		      u8 op_code, bool update);
283 int cs_dsp_wseq_multi_write(struct cs_dsp *dsp, struct cs_dsp_wseq *wseq,
284 			    const struct reg_sequence *reg_seq, int num_regs,
285 			    u8 op_code, bool update);
286 
287 /**
288  * struct cs_dsp_chunk - Describes a buffer holding data formatted for the DSP
289  * @data:	Pointer to underlying buffer memory
290  * @max:	Pointer to end of the buffer memory
291  * @bytes:	Number of bytes read/written into the memory chunk
292  * @cache:	Temporary holding data as it is formatted
293  * @cachebits:	Number of bits of data currently in cache
294  */
295 struct cs_dsp_chunk {
296 	u8 *data;
297 	u8 *max;
298 	int bytes;
299 
300 	u32 cache;
301 	int cachebits;
302 };
303 
304 /**
305  * cs_dsp_chunk() - Create a DSP memory chunk
306  * @data: Pointer to the buffer that will be used to store data
307  * @size: Size of the buffer in bytes
308  *
309  * Return: A cs_dsp_chunk structure
310  */
311 static inline struct cs_dsp_chunk cs_dsp_chunk(void *data, int size)
312 {
313 	struct cs_dsp_chunk ch = {
314 		.data = data,
315 		.max = data + size,
316 	};
317 
318 	return ch;
319 }
320 
321 /**
322  * cs_dsp_chunk_end() - Check if a DSP memory chunk is full
323  * @ch: Pointer to the chunk structure
324  *
325  * Return: True if the whole buffer has been read/written
326  */
327 static inline bool cs_dsp_chunk_end(struct cs_dsp_chunk *ch)
328 {
329 	return ch->data == ch->max;
330 }
331 
332 /**
333  * cs_dsp_chunk_bytes() - Number of bytes written/read from a DSP memory chunk
334  * @ch: Pointer to the chunk structure
335  *
336  * Return: Number of bytes read/written to the buffer
337  */
338 static inline int cs_dsp_chunk_bytes(struct cs_dsp_chunk *ch)
339 {
340 	return ch->bytes;
341 }
342 
343 /**
344  * cs_dsp_chunk_valid_addr() - Check if an address is in a DSP memory chunk
345  * @ch: Pointer to the chunk structure
346  *
347  * Return: True if the given address is within the buffer
348  */
349 static inline bool cs_dsp_chunk_valid_addr(struct cs_dsp_chunk *ch, void *addr)
350 {
351 	return (u8 *)addr >= ch->data && (u8 *)addr < ch->max;
352 }
353 
354 int cs_dsp_chunk_write(struct cs_dsp_chunk *ch, int nbits, u32 val);
355 int cs_dsp_chunk_flush(struct cs_dsp_chunk *ch);
356 int cs_dsp_chunk_read(struct cs_dsp_chunk *ch, int nbits);
357 
358 void cs_dsp_hibernate(struct cs_dsp *dsp, bool hibernating);
359 
360 #endif
361